#!/bin/bash 

#iptables -A INPUT -j ACCEPT -p udp -s 10.28.64.1 --sport 67 --dport 68

#
# Structure of this firewall script:
# - use the astium-examine-network-setup script to find out about the current setup
# - clear all firewall rules
# - define our own chains
# - steer traffic from the standard INPUT, FORWARD and OUTPUT chains into our own chains
#
MYNAME=`basename $0`
VERBOSE=0		# if 1 tells you what it is doing 
DEBUG=0			# if 1 shows all command as they are executed
NOEXEC=0 		# if 1 don't really exec commands
INFOONLY=0		# if 1 only display info on the current network setup
LOGLEVEL=debug		# logging facility
RATELIMIT="100/sec"	# value for rate-limiting incoming tcp connections
BURST="300"		# burst for rate-limiting
IANA="/usr/local/astium/etc/firewall/iana-reserved" # iana list with reserved ips
#------------------------------------------------------------------------------
# Echo function for debugging
#------------------------------------------------------------------------------
myecho ()
{
  if [ $VERBOSE = 1 ]
  then
    echo "--> $@"
  fi
}

#------------------------------------------------------------------------------
# Function to use instead of using /sbin/iptables directly, 
# can be used for debugging.
#------------------------------------------------------------------------------
ipt()
{
  if [ $DEBUG = 1 ]
  then
    echo /sbin/iptables "$@"
  fi
  if [ $NOEXEC = 0 ]
  then
    /sbin/iptables "$@"
  fi
}

#------------------------------------------------------------------------------
# Function to use instead of using /sbin/iptables directly, 
# can be used for debugging.
#------------------------------------------------------------------------------
iptlog()
{
  ipt -A $1 $2 -j LOG -m limit --limit 5/minute --limit-burst 5 --log-level $LOGLEVEL --log-prefix "$1: "
}

#------------------------------------------------------------------------------
# clear all chains
#------------------------------------------------------------------------------
flush_chains()
{
  chains=`cat /proc/net/ip_tables_names 2>/dev/null`
  myecho "Flushing all chains"
  for i in $chains; do ipt -t $i -F; done
  myecho "Removing user defined chains"
  for i in $chains; do ipt -t $i -X; done 
}

#------------------------------------------------------------------------------
# Set all rules to default accept
#------------------------------------------------------------------------------
default_accept()
{
  myecho $"Resetting built-in chains to the default ACCEPT policy:"
  ipt -t filter -P INPUT ACCEPT 
  ipt -t filter -P OUTPUT ACCEPT 
  ipt -t filter -P FORWARD ACCEPT 
  ipt -t nat -P PREROUTING ACCEPT 
  ipt -t nat -P POSTROUTING ACCEPT
  ipt -t nat -P OUTPUT ACCEPT
  ipt -t mangle -P PREROUTING ACCEPT
  ipt -t mangle -P OUTPUT ACCEPT
}

#------------------------------------------------------------------------------
# Lock stuff.
#------------------------------------------------------------------------------
LOCKFILE=/tmp/firewall.lck
if [ -f $LOCKFILE ]
then
  kill -9 `cat $LOCKFILE`
  rm -f $LOCKFILE
  echo "firewall killed"
fi

#------------------------------------------------------------------------------
# Creating new lock for current running of firewall scripts.
#------------------------------------------------------------------------------
echo $$ > $LOCKFILE
#echo "Creating firewall lock $$"

#------------------------------------------------------------------------------
# Remove lock file.
#------------------------------------------------------------------------------
unlock() {
  OLD=`cat $LOCKFILE`
  CUR=$$

  if [ $OLD -eq $CUR ]
  then
    #echo removing lock file $OLD $CUR
    rm -f $LOCKFILE
  fi
}

#------------------------------------------------------------------------------
# External rules written by create.config.
# File format: protocol port  destination
#------------------------------------------------------------------------------
CONFDIR=/usr/local/astium/etc/firewall
PROXYARPSCRIPT=$CONFDIR/proxyarp.sh

# config files for outgoing connections originating on internal network
INTERNAL_TO_EXTERNAL=$CONFDIR/internal_to_external
INTERNAL_TO_EXTERNAL_MANUAL=$CONFDIR/internal_to_external.manual

# config files for connections to the DMZ originating on internal network
INTERNAL_TO_DMZ=$CONFDIR/internal_to_dmz
INTERNAL_TO_DMZ_MANUAL=$CONFDIR/internal_to_dmz.manual

# config files for internal connections
INTERNAL_TO_INTERNAL_MANUAL=$CONFDIR/internal_to_internal.manual

# config files for connections from the DMZ to an internal network
DMZ_TO_INTERNAL=$CONFDIR/dmz_to_internal
DMZ_TO_INTERNAL_MANUAL=$CONFDIR/dmz_to_internal.manual

# config files for connections from the DMZ to an internal network
DMZ_TO_EXTERNAL=$CONFDIR/dmz_to_external
DMZ_TO_EXTERNAL_MANUAL=$CONFDIR/dmz_to_external.manual

# config files for internal connections within the DMZ
DMZ_TO_DMZ_MANUAL=$CONFDIR/dmz_to_dmz.manual

# config files for connections from outside to the DMZ
EXTERNAL_TO_DMZ=$CONFDIR/external_to_dmz
EXTERNAL_TO_DMZ_MANUAL=$CONFDIR/external_to_dmz.manual

# config files for connections to the external interface
TO_INTF_EXTERNAL=$CONFDIR/to_intf_external
EXTERNAL_TO_INTERNAL=$CONFDIR/external_to_internal

# locally defined user chains
LOCAL_USER_CHAINS=$CONFDIR/local_user_chains

# locally defined special rules
LOCAL_RULES=$CONFDIR/local_rules

# if this file exists, we don't do anti-spoofing
NOANTISPOOFING=$CONFDIR/no_anti_spoofing

# the following files just contain shell commands so can do pretty much anything
#
ASTIUM_IPTABLES_MODPROBE=$CONFDIR/astium-iptables.modprobe

#------------------------------------------------------------------------------
# this should be in /etc/sysctl.conf
#------------------------------------------------------------------------------
if [ -f /proc/sys/net/ipv4/ip_forward ]
then
  echo "1"     > /proc/sys/net/ipv4/ip_forward
fi
if [ -f /proc/sys/net/ipv4/tcp_syncookies ]
then
  echo "1"     > /proc/sys/net/ipv4/tcp_syncookies
fi
if [ -f /proc/sys/net/ipv4/conf/all/log_martians ]
then
  echo "0"     > /proc/sys/net/ipv4/conf/all/log_martians
fi
if [ -f /proc/sys/net/ipv4/ip_conntrack_max ]
then
  echo "20000" > /proc/sys/net/ipv4/ip_conntrack_max
fi

#------------------------------------------------------------------------------
# uses /proc rp_filter values to drop connections from non-routable ips
#------------------------------------------------------------------------------
for blah in /proc/sys/net/ipv4/conf/*/rp_filter; do
 echo "1" > $blah
done
# Required(?) by FreeS/WAN
echo "0" > /proc/sys/net/ipv4/conf/eth0/rp_filter

#------------------------------------------------------------------------------
# We always have a base firewall setting. 
#
# Further settings may be changed by:     the following action should be performed:
#---------------------------------------+----------------------------------------------+
# 1. add/delete permanent interface     | recreate all rules
#---------------------------------------+----------------------------------------------+
# 2. ip address of existing interface   | only rules that reference this interface
#    changes (DHCP)                     | are changed
#---------------------------------------+----------------------------------------------+
# 3. add/delete temp interface (ppp0),  | interface should add itself
#    maybe while changing ip address    |
#---------------------------------------+----------------------------------------------+
# 4. add/delete VPN client              | 
#---------------------------------------+----------------------------------------------+
# 5. open/close port or range of ports  | into database, add itself
#---------------------------------------+----------------------------------------------+
# 6. add/remove routing                 | 
#---------------------------------------+----------------------------------------------+
# 7. add ip alias                       |
#---------------------------------------+----------------------------------------------+
# BUT FOR SIMPLICITY, WE JUST RERUN THIS SCRIPT ON EVERY CHANGE
#
while test $# -gt 0; do
  case "$1" in
    -d | --debug | --d* )
      DEBUG=1
      shift;;
    -v | --verbose | --v* )
      VERBOSE=1
      shift;;
    -i | --info-only | --i* )
      INFOONLY=1
      shift;;
    -l | --log-level | --l* )
      LOGLEVEL=info
      shift;;
    -n | --noexec | --n* )
      NOEXEC=1
      shift;;
    -r | --rate-limit | --r* )
      shift
      RATELIMIT="$1"
      shift;;
    -b | --burst | --b* )
      shift
      BURST="$1"
      shift;;
    --stop | stop )
      flush_chains
      default_accept
      /sbin/iptables-save -c > /etc/sysconfig/iptables  2>/dev/null
      unlock
      exit 0;;
    --status | status )
      ipt -n -L
      unlock
      exit 0;;
    --start | start )
      break ;;
    * )
      echo "Usage: $0 [flags] [start|stop|status]"
      echo "  Flg Option-Name    Description"
      echo "   -d debug          show every iptables command executed"
      echo "   -i info-only      show current network setup"
      echo "   -l log-level      log with 'info' instead of 'debug'"
      echo "   -n noexec         fake. don't actually do anything"
      echo "   -v verbose        show more info as you proceed"
      echo "   -r rate-limit     set rate-limit (default $RATELIMIT)"
      echo "   -b burst          set burst value (default ($BURST)"
      unlock
      exit 1;;
  esac
done

#------------------------------------------------------------------------------
# source network determination script
# this script looks at the current routing/interface setup, 
# and prepares a lot of variables for our use.
#------------------------------------------------------------------------------
EXAMINE=/usr/local/astium/bin/examine-network-setup
if [ ! -x $EXAMINE ]
then
  echo "I need $EXAMINE, it's not there (or not executable)"
  unlock
  exit 1
fi

. $EXAMINE

#------------------------------------------------------------------------------
# from here on we have the following defined:
#------------------------------------------------------------------------------
# INTERFACES		LIST 	of all interfaces, except aliases and lo
# INTF_INTERNAL		LIST	like INTERFACES but without external, dmz 
# NET_INTERNAL		LIST	of local networks (including remote VPNs)
# INTF_EXTERNAL		NAME	of external interface
# INTF_DMZ		NAME	of DMZ interface
# NET_DMZ 		LIST	of DMZ networks
# IP_INTF_EXTERNAL	ADDRESS	of external interface
# IP_INTF_DMZ		ADDRESS	of DMZ interface
# IP_INTF_INTERNAL	LIST 	of ip addresses of internal interface
# NEONOVAFIREWALL	LIST	of firewalls to allow access from
# NEONOVANET		LIST	of neonova internal networks
# NEONOVADMZ		LIST	of neonova DMZ networks
# NEONOVABB		ADDRESS	of neonova Big Brother

if [ "$INFOONLY" = "1" ]
then
  unlock
  exit 1
fi

if [ "$INTF_EXTERNAL" = "none" ]
then
  echo "no default gateway - quitting"
  unlock
  exit 1
fi

#------------------------------------------------------------------------------
# Start. First set up environment
#------------------------------------------------------------------------------
if [ -x $ASTIUM_IPTABLES_MODPROBE ]
then
  . $ASTIUM_IPTABLES_MODPROBE
else
  modprobe ip_tables
  modprobe ip_conntrack
  modprobe ip_conntrack_ftp ports=21,121
  modprobe ip_nat_ftp ports=21,121
fi

# Required by FreeS/WAN
echo "0" > /proc/sys/net/ipv4/conf/$INTF_EXTERNAL/rp_filter

# Do xen specific stuff.
if [ -d /proc/xen ]
then
        for interface in $INTERFACES
        do
                /sbin/ethtool -K $interface tx off
        done
fi

# Allow total access to al xendomainU, ,each xendomainU has to run its own firewall.
if [ -x "/usr/sbin/xm" ]
then
	$SETUP -A FORWARD -m physdev --physdev-in  vif+ -j ACCEPT
	$SETUP -A FORWARD -m physdev --physdev-out vif+ -j ACCEPT
fi

#------------------------------------------------------------------------------
# Reset all rules.
#------------------------------------------------------------------------------
myecho "reset all rules"
flush_chains

#------------------------------------------------------------------------------
# The default policy is to drop everything.
#------------------------------------------------------------------------------
myecho "Default policies"
ipt --policy INPUT   DROP
ipt --policy FORWARD DROP
ipt --policy OUTPUT  DROP

#------------------------------------------------------------------------------
# Count traffic - define two user chains here for it. The first define
# two rules for incoming packets, and two for outgoing
#------------------------------------------------------------------------------
myecho "IP_ACCOUNTING_IN"
ipt --new-chain IP_ACCOUNTING_IN
# only count totals for now
ipt -A IP_ACCOUNTING_IN
ipt -A IP_ACCOUNTING_IN -j RETURN

myecho "IP_ACCOUNTING_OUT"
ipt --new-chain IP_ACCOUNTING_OUT
# only count totals for now
ipt -A IP_ACCOUNTING_OUT
ipt -A IP_ACCOUNTING_OUT -j RETURN

ipt -A INPUT   -i $INTF_EXTERNAL -j IP_ACCOUNTING_IN
ipt -A FORWARD -i $INTF_EXTERNAL -j IP_ACCOUNTING_IN
ipt -A FORWARD -o $INTF_EXTERNAL -j IP_ACCOUNTING_OUT
ipt -A OUTPUT  -o $INTF_EXTERNAL -j IP_ACCOUNTING_OUT

#------------------------------------------------------------------------------
# this allows traffic for already established connections
#------------------------------------------------------------------------------
myecho "Basics"
ipt -A INPUT   -m state --state RELATED,ESTABLISHED -j ACCEPT
ipt -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
ipt -A OUTPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT

#------------------------------------------------------------------------------
#
# Define our own chains
#
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# USER CHAIN: DEBUG
#------------------------------------------------------------------------------
myecho "chain for debugging"
ipt --new-chain DEBUG
iptlog "DEBUG"
ipt -A DEBUG -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: SPOOFED
# we want to know about spoofed traffic, as this is clearly a hacking attempt
#------------------------------------------------------------------------------
myecho "chain for logging spoofed traffic"
ipt --new-chain SPOOFED
iptlog "SPOOFED"
ipt -A SPOOFED -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: RATE_LIMIT
# We rate-limit incoming connections on the external interface, 
# to protect against SYN-flooding
#------------------------------------------------------------------------------
myecho "user chain for rate-limiting incoming connections"
ipt --new-chain RATE_LIMIT
ipt -A RATE_LIMIT -m limit --limit $RATELIMIT --limit-burst $BURST -j RETURN
iptlog "RATE_LIMIT"
ipt -A RATE_LIMIT -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: FRAGMENTS
# Do NOT trust fragments at all. Log them to see if we get them
#------------------------------------------------------------------------------
myecho "user chain for logging fragments"
ipt --new-chain FRAGMENTS
iptlog "FRAGMENTS"
ipt -A FRAGMENTS -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: ACCEPT_ICMP 
#------------------------------------------------------------------------------
myecho "ICMP rules chain: only accept certain types of packets."
ipt --new-chain ACCEPT_ICMP

# icmp requires special handling, 
# because some ICMP packets give out too much information
for type in destination-unreachable source-quench time-exceeded parameter-problem ping echo-request echo-reply
do
  ipt -A ACCEPT_ICMP --proto ICMP -s 0/0 --icmp-type $type -j ACCEPT
done

# log and drop the rest
iptlog "ACCEPT_ICMP"
ipt -A ACCEPT_ICMP -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: ACCEPT_TCP
# handle TCP connections. If we get here the port to connect to has already been approved
#------------------------------------------------------------------------------
myecho "ACCEPT_TCP, watch stateful connections"
ipt --new-chain ACCEPT_TCP

# initial connection packet: always ok
ipt -A ACCEPT_TCP --proto TCP --syn -j ACCEPT

# allow packets from existing connections
ipt -A ACCEPT_TCP --proto TCP --match state --state NEW,ESTABLISHED,RELATED -j ACCEPT


# log and drop the rest
iptlog "ACCEPT_TCP"
ipt -A ACCEPT_TCP -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: ACCEPT_IPV6_CRYPT
# handle IPSEC connections
#------------------------------------------------------------------------------
myecho "ACCEPT_IPV6_CRYPT, handle IPSEC"
ipt --new-chain ACCEPT_IPV6_CRYPT
ipt -A ACCEPT_IPV6_CRYPT --proto 50 -j ACCEPT

#------------------------------------------------------------------------------
# USER CHAIN: ACCEPT_ALL
# split into various protocols
#------------------------------------------------------------------------------
myecho "ACCEPT_ALL, watch stateful connections"
ipt --new-chain ACCEPT_ALL
ipt -A ACCEPT_ALL --proto TCP -j ACCEPT_TCP
ipt -A ACCEPT_ALL --proto UDP -j ACCEPT

# log and drop the rest
iptlog "ACCEPT_ALL"
ipt -A ACCEPT_ALL -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: TO_INTF_EXTERNAL
# handle packets directed to the external interface
#------------------------------------------------------------------------------
myecho "TO_INTF_EXTERNAL"
ipt --new-chain TO_INTF_EXTERNAL

# if they come through the internal interface, accept them.
for intf in $INTF_INTERNAL ipsec0
do
  ipt -A TO_INTF_EXTERNAL --protocol ALL -i $intf -j ACCEPT_ALL
done

if [ "$HAVE_DMZ" = "yes" ]
then
  # if they come in through the DMZ interface, accept them.
  ipt -A TO_INTF_EXTERNAL --protocol ALL -i $INTF_DMZ -j ACCEPT_ALL
fi

# Define port forwarding from the internet to internal servers.
myecho "Port forwarding to internal servers"
if [ -f $EXTERNAL_TO_INTERNAL ]
then
  while read PROTO SRC DEST DPORT INT IPORT
  do
    if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
    then
      continue
    fi
    if [ "$IPORT" = "" ]
    then
      IPORT=$INT
      INT=$DPORT
      DPORT=$DEST
      DEST=$SRC
      SRC=0.0.0.0/0
    fi
    ipt -t nat -A PREROUTING -p $PROTO -s $SRC -d $DEST --dport $DPORT -j DNAT --to-destination $INT:$IPORT
    ipt -A FORWARD -p $PROTO -s $SRC -d $INT --dport $IPORT -j ACCEPT
  done < $EXTERNAL_TO_INTERNAL
fi

# specific ports to be opened from the outside to the external interface
if [ -f $TO_INTF_EXTERNAL ]
then
  while read PROTO SOURCE PORT JUMP
  do
    if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
    then
      continue
    fi
    ipt -A TO_INTF_EXTERNAL --protocol $PROTO -s $SOURCE --dport $PORT -j $JUMP
  done < $TO_INTF_EXTERNAL
fi

# deny connections to port auth (113) with a TCP RST. 
# Some mail servers (and other things) don't work without it.
ipt -A TO_INTF_EXTERNAL --protocol TCP --dport auth -i $INTF_EXTERNAL -j REJECT --reject-with tcp-reset

# Allow neonova network and firewall ssh access to login.
for firewall in $NEONOVAFIREWALL
do
  ipt -A TO_INTF_EXTERNAL --protocol TCP --dport ssh -s $firewall -i $INTF_EXTERNAL -j ACCEPT_ALL
done
for net in $NEONOVANET
do
  ipt -A TO_INTF_EXTERNAL --protocol TCP --dport ssh -s $net -i $INTF_EXTERNAL -j ACCEPT_ALL
done

# accept mail from backup MX hosts and 
# deny other connections to port 25 (smtp) with a TCP RST. 
# If no MX hosts are set, allow ALL connections to port smtp
if [ "$ALLOWEDMXHOSTS" = "" ]
then
  ipt -A TO_INTF_EXTERNAL --protocol TCP --dport smtp -i $INTF_EXTERNAL -j ACCEPT_ALL
else
  for mxhost in $ALLOWEDMXHOSTS $NEONOVABB
  do
    ipt -A TO_INTF_EXTERNAL --protocol TCP --dport smtp -s $mxhost -i $INTF_EXTERNAL -j ACCEPT_ALL
  done
  ipt -A TO_INTF_EXTERNAL --protocol TCP --dport smtp -i $INTF_EXTERNAL -j REJECT --reject-with tcp-reset
fi

ipt -A TO_INTF_EXTERNAL --protocol TCP --dport smtp -s 217.170.32.68 -i $INTF_EXTERNAL -j ACCEPT_ALL
ipt -A TO_INTF_EXTERNAL --protocol TCP --dport smtp -s 217.170.32.69 -i $INTF_EXTERNAL -j ACCEPT_ALL

# allow incoming IPSEC traffic
ipt -A TO_INTF_EXTERNAL --proto 50 -j ACCEPT_IPV6_CRYPT

# block the rest
iptlog "TO_INTF_EXTERNAL"
ipt -A TO_INTF_EXTERNAL -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: TO_INTF_DMZ
# packets directly to the DMZ interface
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "TO_INTF_DMZ"
  ipt --new-chain TO_INTF_DMZ
  # drop if coming from outside
  ipt -A TO_INTF_DMZ -i $INTF_EXTERNAL -j DROP
  # accept the rest
  ipt -A TO_INTF_DMZ -j ACCEPT_ALL
fi

#------------------------------------------------------------------------------
# USER CHAIN: TO_INTF_INTERNAL
# packets directly aimed at (one of the) internal interface(s)
#------------------------------------------------------------------------------
myecho "TO_INTF_INTERNAL"
ipt --new-chain TO_INTF_INTERNAL

# if they come from outside - drop them
iptlog "TO_INTF_INTERNAL" "-i $INTF_EXTERNAL"
ipt -A TO_INTF_INTERNAL -i $INTF_EXTERNAL -j DROP

# accept the rest
ipt -A TO_INTF_INTERNAL -j ACCEPT_ALL

#------------------------------------------------------------------------------
# USER CHAIN: TO_IP_ALIASES
#------------------------------------------------------------------------------
myecho "TO_IP_ALIASES (virtual hosts)"
ipt --new-chain TO_IP_ALIASES

# Allow ftp,telnet,ssh,smtp,pop-3,imap,https,http connections to virtual hosts
for service in ftp telnet ssh smtp pop-3 imap http https 
do
  ipt -A TO_IP_ALIASES --protocol TCP --dport $service -j ACCEPT
done

# Drop any packets to ip aliases that are not specifically allowed
iptlog "TO_IP_ALIASES"
ipt -A TO_IP_ALIASES -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: INTERNAL_TO_DMZ
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "INTERNAL_TO_DMZ, allow all"
  ipt --new-chain INTERNAL_TO_DMZ 

  # ports to be opened to the DMZ
  if [ -f $INTERNAL_TO_DMZ ]
  then 
    while read PROTO SOURCE DEST PORT JUMP
    do
      if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
      then
        continue
      fi
      ipt -A INTERNAL_TO_DMZ --protocol $PROTO -s $SOURCE -d $DEST --dport $PORT -j $JUMP
    done < $INTERNAL_TO_DMZ
  fi

  # Run the script (if present) for outgoing connections. Hopefully rarely needed
  if [ -x $INTERNAL_TO_DMZ_MANUAL ]
  then
    . $INTERNAL_TO_DMZ_MANUAL
  fi

  iptlog "INTERNAL_TO_DMZ"
  ipt -A INTERNAL_TO_DMZ -j DROP
fi

#------------------------------------------------------------------------------
# USER CHAIN: INTERNAL_TO_INTERNAL
#------------------------------------------------------------------------------
myecho "INTERNAL_TO_INTERNAL"
ipt --new-chain INTERNAL_TO_INTERNAL
if [ -x $INTERNAL_TO_INTERNAL_MANUAL ]
then
  . $INTERNAL_TO_INTERNAL_MANUAL
fi
ipt -A INTERNAL_TO_INTERNAL -j ACCEPT
iptlog "INTERNAL_TO_INTERNAL"
ipt -A INTERNAL_TO_INTERNAL -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: INTERNAL_TO_EXTERNAL
#------------------------------------------------------------------------------
myecho "INTERNAL_TO_EXTERNAL"
ipt --new-chain INTERNAL_TO_EXTERNAL

# ports to be opened to the outside
if [ -f $INTERNAL_TO_EXTERNAL ]
then # protocol source destination port WHAT
  while read PROTO SOURCE DEST PORT JUMP
  do
    if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
    then
      continue
    fi
    ipt -A INTERNAL_TO_EXTERNAL --protocol $PROTO -s $SOURCE -d $DEST --dport $PORT -j $JUMP
  done < $INTERNAL_TO_EXTERNAL
fi

# Run the script (if present) for outgoing connections. Hopefully rarely needed
if [ -x $INTERNAL_TO_EXTERNAL_MANUAL ]
then
  . $INTERNAL_TO_EXTERNAL_MANUAL
fi

# Drop any outgoing packets that are not specifically allowed
iptlog "INTERNAL_TO_EXTERNAL"
ipt -A INTERNAL_TO_EXTERNAL -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: FROM_INTERNAL
#------------------------------------------------------------------------------
myecho "FROM_INTERNAL"
ipt --new-chain FROM_INTERNAL
if [ "$HAVE_DMZ" = "yes" ]
then
  for net in $NET_DMZ
  do
    ipt -A FROM_INTERNAL -d $net -j INTERNAL_TO_DMZ
  done
fi
for net in $NET_INTERNAL
do
  ipt -A FROM_INTERNAL -d $net -j INTERNAL_TO_INTERNAL
done
ipt -A FROM_INTERNAL -j INTERNAL_TO_EXTERNAL
iptlog "FROM_INTERNAL"
ipt -A FROM_INTERNAL -j DROP

#------------------------------------------------------------------------------
# USER CHAIN: DMZ_TO_INTERNAL
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "DMZ_TO_INTERNAL"
  ipt --new-chain DMZ_TO_INTERNAL

  # ports to be opened to the internal network
  if [ -f $DMZ_TO_INTERNAL ]
  then 
    while read PROTO SOURCE DEST PORT JUMP
    do
      if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
      then
        continue
      fi
      ipt -A DMZ_TO_INTERNAL --protocol $PROTO -s $SOURCE -d $DEST --dport $PORT -j $JUMP
    done < $DMZ_TO_INTERNAL
  fi

  # Run the script (if present) for outgoing connections. Hopefully rarely needed
  if [ -x $DMZ_TO_INTERNAL_MANUAL ]
  then
    . $DMZ_TO_INTERNAL_MANUAL
  fi

  iptlog "DMZ_TO_INTERNAL"
  ipt -A DMZ_TO_INTERNAL -j DROP
fi

#------------------------------------------------------------------------------
# USER CHAIN: DMZ_TO_DMZ
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "DMZ_TO_DMZ"
  ipt --new-chain DMZ_TO_DMZ
  if [ -x $DMZ_TO_DMZ_MANUAL ]
  then
    . $DMZ_TO_DMZ_MANUAL
  fi
  ipt -A DMZ_TO_DMZ -j ACCEPT
  iptlog "DMZ_TO_DMZ"
  ipt -A DMZ_TO_DMZ -j DROP
fi

#------------------------------------------------------------------------------
# USER CHAIN: DMZ_TO_EXTERNAL
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "DMZ_TO_EXTERNAL"
  ipt --new-chain DMZ_TO_EXTERNAL

  # ports to be opened to the internal network
  if [ -f $DMZ_TO_EXTERNAL ]
  then 
    while read PROTO SOURCE DEST PORT JUMP
    do
      if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
      then
        continue
      fi
      ipt -A DMZ_TO_EXTERNAL --protocol $PROTO -s $SOURCE -d $DEST --dport $PORT -j $JUMP
    done < $DMZ_TO_EXTERNAL
  fi

  # Run the script (if present) for outgoing connections. Hopefully rarely needed
  if [ -x $DMZ_TO_EXTERNAL_MANUAL ]
  then
    . $DMZ_TO_EXTERNAL_MANUAL
  fi

  iptlog "DMZ_TO_EXTERNAL"
  ipt -A DMZ_TO_EXTERNAL -j DROP
fi

#------------------------------------------------------------------------------
# USER CHAIN: FROM_DMZ
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "FROM_DMZ"
  ipt --new-chain FROM_DMZ
  for net in $NET_INTERNAL
  do
    ipt -A FROM_DMZ -d $net -j DMZ_TO_INTERNAL
  done
  for net in $NET_DMZ
  do
    ipt -A FROM_DMZ -d $net -j DMZ_TO_DMZ
  done
  ipt -A FROM_DMZ -j DMZ_TO_EXTERNAL
  iptlog "FROM_DMZ"
  ipt -A FROM_DMZ -j DROP
fi

#------------------------------------------------------------------------------
# USER CHAIN: EXTERNAL_TO_DMZ
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "EXTERNAL_TO_DMZ"
  ipt --new-chain EXTERNAL_TO_DMZ

  # ports to be opened to the internal network
  if [ -f $EXTERNAL_TO_DMZ ]
  then 
    while read PROTO SOURCE DEST PORT JUMP
    do
      if [ "${PROTO:0:1}" = "#" -o "${PROTO:0:1}" = " " -o "$PROTO" = "" ]
      then
        continue
      fi
      ipt -A EXTERNAL_TO_DMZ --protocol $PROTO -s $SOURCE -d $DEST --dport $PORT -j $JUMP
    done < $EXTERNAL_TO_DMZ
  fi

  # Run the script (if present) for outgoing connections. Hopefully rarely needed
  if [ -x $EXTERNAL_TO_DMZ_MANUAL ]
  then
    . $EXTERNAL_TO_DMZ_MANUAL
  fi

  # log and drop the rest
  iptlog "EXTERNAL_TO_DMZ"
  ipt -A EXTERNAL_TO_DMZ -j DROP
fi

#------------------------------------------------------------------------------
# USER CHAIN: FROM_EXTERNAL
#------------------------------------------------------------------------------
myecho "FROM_EXTERNAL"
ipt --new-chain FROM_EXTERNAL
if [ "$HAVE_DMZ" = "yes" ]
then
  for net in $NET_DMZ
  do
    ipt -A FROM_EXTERNAL -d $net -j EXTERNAL_TO_DMZ
  done
fi
# ipt -A FROM_EXTERNAL -j EXTERNAL_TO_EXTERNAL
iptlog "FROM_EXTERNAL"
ipt -A FROM_EXTERNAL -j DROP

#------------------------------------------------------------------------------
# Locally defined USER CHAINS
#------------------------------------------------------------------------------
if [ -x $LOCAL_USER_CHAINS ]
then
  . $LOCAL_USER_CHAINS
fi

#******************************************************************************
#                                                                             *
#                        ACTUAL START OF PROCESSING                           *
#                                                                             *
# Redirect traffic in INPUT, FORWARD, OUTPUT into our own chains              *
#                                                                             *
#******************************************************************************

# Important: allow the machine to configure itself using DHCP
ipt -A INPUT -i $INTF_EXTERNAL -p TCP -s 0.0.0.0 --dport 67 -j ACCEPT
ipt -A INPUT -j ACCEPT -p udp --sport 67 --dport 68

#------------------------------------------------------------------------------
# drop spoofed packets
# but take special measures for neonova internal use
#------------------------------------------------------------------------------
myecho "Basic error/spoof checking"

if [ -f $NOANTISPOOFING ] 
then
  # don't enable anti-spoofing
  ipt -A INPUT   --proto ICMP -j ACCEPT_ICMP
  ipt -A OUTPUT  --proto ICMP -j ACCEPT_ICMP
  ipt -A INPUT -i $INTF_EXTERNAL -s $NEONOVANET -d $IP_INTF_EXTERNAL -j TO_INTF_EXTERNAL
else
  # enable anti-spoofing 
  ipt -A INPUT -i $INTF_EXTERNAL -s 192.168.0.0/16 -j SPOOFED
fi

#------------------------------------------------------------------------------
# Drop traffic from networks that shouldn't be on the internet at all.
# This should not be necessary when rp_filter are set, but there may
# be a bug in the TCP/IP stack...
# Also drop traffic from non-IANA assigned blocks, for a list see
# http://www.iana.net/assignments/ipv4-address-space
#------------------------------------------------------------------------------
if [ ! -f $NOANTISPOOFING -a -f $IANA ] 
then
  for i in `cat $IANA`; do ipt -A INPUT -i $INTF_EXTERNAL -s $i -j SPOOFED; done
fi

#------------------------------------------------------------------------------
# ICMP is handled in a special way.
#------------------------------------------------------------------------------
myecho "ICMP is handled in a special way"
ipt -A INPUT   --proto ICMP -j ACCEPT_ICMP
ipt -A FORWARD --proto ICMP -j ACCEPT_ICMP
ipt -A OUTPUT  --proto ICMP -j ACCEPT_ICMP

#------------------------------------------------------------------------------
# Direct incoming SYN request to the RATE-LIMIT chain
#------------------------------------------------------------------------------
myecho "Send incoming SYN packets to the RATE_LIMIT chain"
ipt -A INPUT -i $INTF_EXTERNAL -p TCP --syn -j RATE_LIMIT
ipt -A FORWARD -i $INTF_EXTERNAL -p TCP --syn -j RATE_LIMIT

#------------------------------------------------------------------------------
# Log and reject fragments
#------------------------------------------------------------------------------
myecho "Log and reject fragments"
ipt -A INPUT -i $INTF_EXTERNAL -f -p TCP -j FRAGMENTS
ipt -A FORWARD -i $INTF_EXTERNAL -f -p TCP -j FRAGMENTS

#------------------------------------------------------------------------------
# Locally defined special firewall rules
#------------------------------------------------------------------------------
if [ -x $LOCAL_RULES ]
then
  . $LOCAL_RULES
fi

#------------------------------------------------------------------------------
# For all local networks masq outgoing traffic.
#------------------------------------------------------------------------------
myecho "For all local networks masq outgoing traffic"
for localnet in $NET_INTERNAL
do
  ipt --table nat -A POSTROUTING -s $localnet -o $INTF_EXTERNAL -j MASQUERADE
done

#------------------------------------------------------------------------------
# Give priority to ssh access (in- and outbound), easy for remote maintenance..
#------------------------------------------------------------------------------
ipt -A PREROUTING -t mangle -p tcp --dport ssh -j TOS --set-tos Minimize-Delay
ipt -A PREROUTING -t mangle -p tcp --sport ssh -j TOS --set-tos Minimize-Delay
ipt -A OUTPUT -t mangle -p tcp --dport ssh -j TOS --set-tos Minimize-Delay
ipt -A OUTPUT -t mangle -p tcp --sport ssh -j TOS --set-tos Minimize-Delay

#------------------------------------------------------------------------------
# traffic to/from localhost, and outgoing traffic originating from one of our 
# interfaces is always accepted
#------------------------------------------------------------------------------
myecho "accept all from localhost"
ipt -A INPUT -i lo -j ACCEPT
ipt -A OUTPUT -o lo -j ACCEPT

myecho "traffic originating from a specific interface is always allowed"
ipt -A OUTPUT --proto ALL -s $IP_INTF_EXTERNAL -j ACCEPT
if [ "$HAVE_DMZ" = "yes" ]
then
  ipt -A OUTPUT --proto ALL -s $IP_INTF_DMZ -j ACCEPT
fi
for ip in $IP_INTF_INTERNAL
do
  ipt -A OUTPUT --proto ALL -s $ip -j ACCEPT
done

#------------------------------------------------------------------------------
# Allow all outgoing packets originating on the DMZ interface
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  ipt -A INPUT -d $IP_INTF_DMZ -j TO_INTF_DMZ
fi

#------------------------------------------------------------------------------
# Direct all traffic to the external ip address to the TO_INTF_EXTERNAL table
#------------------------------------------------------------------------------
myecho "EXTERNAL interface"
ipt -A INPUT -d $IP_INTF_EXTERNAL -j TO_INTF_EXTERNAL

#------------------------------------------------------------------------------
# Direct all traffic to one of the internal interfaces to TO_INTF_INTERNAL
#------------------------------------------------------------------------------
myecho "INTERNAL interfaces"
for ip in $IP_INTF_INTERNAL
do
  ipt -A INPUT -d $ip -j TO_INTF_INTERNAL
done

#------------------------------------------------------------------------------
# Direct all traffic to one of the aliases (virtual hosts) to TO_IPALIASES
#------------------------------------------------------------------------------
myecho "IP_ALIASES"
for ip in $IP_ALIASES
do
  ipt -A INPUT -d $ip -j TO_IP_ALIASES
done

#------------------------------------------------------------------------------
# Send traffic originating from an internal network to the FROM_INTERNAL CHAIN
#------------------------------------------------------------------------------
myecho "Traffic from internal network"
for source in $NET_INTERNAL
do
  if [ "$HAVE_DMZ" = "yes" ]
  then
    if [ ! -f $NOANTISPOOFING ] 
    then
        ipt -A FORWARD -s $source -i $INTF_DMZ -j SPOOFED
    fi
  fi
  if [ ! -f $NOANTISPOOFING ] 
  then
      ipt -A FORWARD -s $source -i $INTF_EXTERNAL -j SPOOFED
  fi 
  ipt -A FORWARD -s $source -j FROM_INTERNAL
done

#------------------------------------------------------------------------------
# Send traffic originating from a DMZ network to the FROM_DMZ CHAIN
#------------------------------------------------------------------------------
if [ "$HAVE_DMZ" = "yes" ]
then
  myecho "Traffic from DMZ"
  for source in $NET_DMZ
  do   
    if [ ! -f $NOANTISPOOFING ] 
    then
      ipt -A FORWARD -s $source -i $INTF_EXTERNAL -j SPOOFED
    fi
    for intf in $INTF_INTERNAL ipsec0
    do
      if [ ! -f $NOANTISPOOFING ] 
      then
        ipt -A FORWARD -s $source -i $intf -j SPOOFED
      fi 
    done
    ipt -A FORWARD -s $source -j FROM_DMZ
  done
fi

#------------------------------------------------------------------------------
# All the rest comes from external
#------------------------------------------------------------------------------
myecho "Traffic from external network"
for net in $NET_INTERNAL
do
  if [ ! -f $NOANTISPOOFING ] 
  then
    ipt -A FORWARD -d $net -j SPOOFED
  fi
done
ipt -A FORWARD -j FROM_EXTERNAL

myecho "accept broadcasts on internal nets and DMZ"
for intf in $INTF_INTERNAL $INTF_DMZ ipsec0
do
  ipt -A INPUT -i $intf -d 0.0.0.255/0.0.0.255 -j ACCEPT
done

#------------------------------------------------------------------------------
# Log any traffic we missed. Shouldn't happen.
#------------------------------------------------------------------------------
iptlog "INPUT"
iptlog "FORWARD"
iptlog "OUTPUT"

# unneeded, but very clear.
ipt -A INPUT   -j DROP
ipt -A FORWARD -j DROP
ipt -A OUTPUT  -j DROP

#------------------------------------------------------------------------------
# save current config so iptables restart will pick 'm up
#------------------------------------------------------------------------------
/sbin/iptables-save -c > /etc/sysconfig/iptables  2>/dev/null
if [ -x $PROXYARPSCRIPT ]
then
  $PROXYARPSCRIPT 
fi
unlock
exit 0

