#!/bin/sh
#
# KONI - SGN Firewall Configuration
# Rewritten (slightly) for iptables, 2005 05 09, Marty
# Checked into svn, Groundhog's Day, 2006, Marty
#
# --- EMACS USERS ---
# If you are having problems with getting the backspace key to delete instead
# of invoke help, move the cursor to the end of the lisp expression below and
# press C-x C-e 
#
# (global-set-key "\C-h" 'delete-backward-char)
#
# Note: This will stop C-h working as the Help prefix key.  For
# recentish emacsen, try M-x normal-erase-is-backspace-mode.  -- Marty

# Prerequisites, possibly not relevant.  It's hard to probe the kernel
# for features and behaviors.
PATH=/sbin:/usr/sbin:/usr/local/sbin:${PATH}
test -x /sbin/iptables || (echo "ERROR: iptables command not found" && exit 1)
iptables -L >/dev/null 2>/dev/null
if [ $? -ne 0 ]; then # iptables failed
  echo "iptables command failed, trying to load module"
  modprobe iptables # try loading the module
  iptables -L >/dev/null 2>/dev/null # try iptables again
  if [ $? -ne 0 ]; then # bail out.
    echo "ERROR: iptables module failing to load.  kernel may not support it."
    exit 1
  fi
fi

echo -n "Starting firewall..."
# Disable ip_forwarding policy (will be enabled in a few lines).
echo 0 > /proc/sys/net/ipv4/ip_forward

# Flush all tables
iptables --flush # flush default table (filter table)
#iptables -t nat --flush # flush nat table (no nat defined yet, 2005 05 10)

# Set up the `firewall' chain.
iptables -N firewall 2> /dev/null
iptables -A firewall -j LOG --log-level info --log-prefix "Firewall: "
iptables -A firewall -j DROP

# Set default policies for default chains in filter table.
#iptables -P INPUT DROP
#iptables -P OUTPUT DROP
#iptables -P FORWARD DROP

# Re-enable packet forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# Our network interfaces.  Unfortunately, their identities depend on
# the order that the drivers get loaded, so make sure these remain
# fixed.
#
# eth0: e1000 NIC, 132.236.157.65, i.e., "programmer hole"
hole_addr="132.236.157.65"
hole_net="132.236.157.64/26"
hole_if="eth0"
# eth1: e1000 NIC, 128.253.40.1, i.e., "lab machines"
lab_addr="128.253.40.1"
lab_net="128.253.40.0/26"
lab_if="eth1"
# eth2: e100 NIC, 132.236.57.214, i.e., "outside world"
world_addr="132.236.57.214"
world_net="" # Note: we never use this concept.
world_if="eth2"
# loopback
lo_addr="127.0.0.1"
lo_net="127.0.0.0/8"
lo_if="lo"

# Allow all incoming traffic on our "internal" interfaces into
# the router host.
iptables -I INPUT -j ACCEPT -s $lab_net
iptables -I INPUT -j ACCEPT -s $hole_net
iptables -I INPUT -j ACCEPT -s $lo_net

# Allow all outgoing traffic on our "internal" interfaces from
# the router host.
iptables -I OUTPUT -j ACCEPT -d $lab_net
iptables -I OUTPUT -j ACCEPT -d $hole_net
iptables -I OUTPUT -j ACCEPT -d $lo_net

# Allow all icmp
iptables -I INPUT -j ACCEPT -p icmp
iptables -I OUTPUT -j ACCEPT -p icmp

#############################################################################
#
# The boilerplate section -- NTP, DNS, outgoing connections, etc. 
#
#############################################################################

# Allow NTP for firewall -- these hosts are ntp{0,1,2}.cornell.edu and
# ntp.lightlink.com, respectively, at the time of writing. This should be 
# periodically verified. We can't use the hostnames here because DNS is not yet
# enabled in the firewall. Also, we don't want DNS spoofs to cause the firewall
# configuration to open ports for hosts we do not trust.

# NOTE: We allow NTP to the firewall host, which is running and ntpd server
#       hosts behind our firewall must use the firewall's ntpd
for NTP_HOST in 132.236.56.250 128.84.154.10 192.35.82.50 207.127.235.1; do
# Allow us to send and receive ntp
iptables -I INPUT -j ACCEPT -p udp --source $NTP_HOST --source-port ntp --destination $world_addr --destination-port ntp
iptables -I OUTPUT -j ACCEPT -p udp --destination $NTP_HOST --destination-port ntp --source $world_addr --source-port ntp
# Forward ntp from/to programmer hole.
iptables -I FORWARD -j ACCEPT -p udp --destination $NTP_HOST --destination-port ntp --source $lab_net --source-port ntp
iptables -I FORWARD -j ACCEPT -p udp --destination $lab_net --destination-port ntp --source $NTP_HOST --source-port ntp
# Forward ntp from/to lab subnet.
iptables -I FORWARD -j ACCEPT -p udp --destination $NTP_HOST --destination-port ntp --source $hole_net --source-port ntp
iptables -I FORWARD -j ACCEPT -p udp --destination $hole_net --destination-port ntp --source $NTP_HOST --source-port ntp
done

# Nameservice
for NAMESERVER in 132.236.56.250 128.253.180.2; do
# Accept our dns query answers.
iptables -I INPUT -j ACCEPT -p udp --source $NAMESERVER --source-port domain --destination-port 1024:65535
# Allow router to make dns queries
iptables -I OUTPUT -j ACCEPT -p udp --source-port 1024:65535 --destination $NAMESERVER --destination-port domain
# Forward dns responses to anywhere.
iptables -I FORWARD -j ACCEPT -p udp --source $NAMESERVER --source-port domain --destination-port 1024:65535
# Forward dns queries from anywhere.
iptables -I FORWARD -j ACCEPT -p udp --source-port 1024:65535 --destination $NAMESERVER --destination-port domain 
done

# Due to experience with CIT's DNS servers being somewhat flaky, we run our
# own BIND on amatxu. It also allows us to lookup host names of some of our
# hosts on private subnets, like the cluster nodes.
#
# What's more, hosts involved in production services (as of 2006/02/02,
# that's sabazius, hyoscine, and solanine) may experience frustrating
# delays if their main dns resolvers are unreachable, so for increased
# autonomy, we'll have each one run its own caching nameserver.
#
# Finally, we want to have at least two hosts serving DNS to the
# subnet in our rack, so that either can be shut down without slowing
# down the entire rack.  amatxu and solanine are the logical candidates.
#          amatxu         solanine       sabazius       hyoscine
dns_hosts="132.236.157.75 132.236.157.82 132.236.157.83 132.236.157.88"
for addr in $dns_hosts; do
  iptables -I FORWARD -j ACCEPT -p udp --destination $addr --destination-port 1024:65535 --source-port domain
  iptables -I FORWARD -j ACCEPT -p udp --destination-port domain --source $addr --source-port 1024:65535 
done

# Allowing tcp connections and return traffic from/to the SGN subnet
iptables -I FORWARD -j ACCEPT -p tcp --source $hole_net
iptables -I FORWARD -j ACCEPT -p tcp --destination $hole_net ! --syn

# Likewise for the LAB subnet
iptables -I FORWARD -j ACCEPT -p tcp --source $lab_net
iptables -I FORWARD -j ACCEPT -p tcp --destination $lab_net ! --syn


#############################################################################
# This section explicitly enables access to certain SGN services.
#
#############################################################################

function allow_port {
    iptables -I FORWARD -j ACCEPT -p tcp --destination-port $1 --destination $2
    iptables -I FORWARD -j ACCEPT -p tcp --source-port $1 --source $2
}
# Allow http to several sgn servers
allow_port 80 www.sgn.cornell.edu
allow_port 80 www.pgn.cornell.edu
allow_port 80 zamir-devel.sgn.cornell.edu
allow_port 80 sgn-devel.sgn.cornell.edu

#allow HTTP on weird port to lycocyc for pathwaytools web interface
allow_port 1555 lycocyc.sgn.cornell.edu

# Allow SSH into protected subnet: Maybe clean this up?
iptables -I FORWARD -j ACCEPT -p tcp --destination-port ssh
iptables -I FORWARD -j ACCEPT -p tcp --source-port ssh

#Allow smtp to rubisco, the be MX for sgn.cornell.edu
iptables -I FORWARD -j ACCEPT -p tcp --destination rubisco.sgn.cornell.edu --destination-port smtp
iptables -I FORWARD -j ACCEPT -p tcp --source rubisco.sgn.cornell.edu --source-port smtp
iptables -I FORWARD -j ACCEPT -p tcp --destination rubisco.sgn.cornell.edu --destination-port www
iptables -I FORWARD -j ACCEPT -p tcp --source rubisco.sgn.cornell.edu --source-port www
iptables -I FORWARD -j ACCEPT -p tcp --destination zamir-devel.sgn.cornell.edu --destination-port www
iptables -I FORWARD -j ACCEPT -p tcp --source zamir-devel.sgn.cornell.edu --source-port www

# Allow ftp to sgn ftp server
iptables -A FORWARD -j ACCEPT -p tcp --destination-port ftp --destination ftp.sgn.cornell.edu 
iptables -A FORWARD -j ACCEPT -p tcp --source-port ftp --source ftp.sgn.cornell.edu 
iptables -A FORWARD -j ACCEPT -p tcp --destination-port ftp-data --destination ftp.sgn.cornell.edu 
iptables -A FORWARD -j ACCEPT -p tcp --source-port ftp-data --source ftp.sgn.cornell.edu 

# Allow zamolxis to connect to a non-standard rsync port on solanine
iptables -A FORWARD -j ACCEPT -p tcp --source 132.236.86.124 --destination solanine.sgn.cornell.edu --destination-port 2222 

# Ports allowed for passive FTP. The ftp server *must* be configured to use
# use this limited range of ports for "passive" FTP connections. Note that if
# some stupid service is started on this range of ports, the outside world can
# access it freely! Do we like that? NO WE DON'T
#
# Proper solution would have the FTP server (and web server too probably) in 
# a demilitarized zone outside the free-for-all-once-you're-inside SGN subnet
iptables -A FORWARD -j ACCEPT -p tcp --destination ftp.sgn.cornell.edu --destination-port 53000:62511
iptables -A FORWARD -j ACCEPT -p tcp --source ftp.sgn.cornell.edu --source-port 53000:62511

# Moby services run through a webserver -- moby was dedicated its own IP 
# because of the need to open the web port to the world.
iptables -A FORWARD -j ACCEPT -p tcp --destination moby.sgn.cornell.edu --destination-port http
iptables -A FORWARD -j ACCEPT -p tcp --source moby.sgn.cornell.edu --source-port http

# Allow known BTI subnets to access the "official" development server site --
# for collaboration with Giovannoni and Martin labs at BTI
for DEVEL_ALLOW in $lab_net 132.236.86.0/24 132.236.156.0/24; do
iptables -A FORWARD -j ACCEPT -p tcp --destination sgn-devel.sgn.cornell.edu --destination-port http --source $DEVEL_ALLOW
done

############################################################################
# SPECIAL CONSIDERATIONS FOR CIT SERVICES
#
# NOTE: This will contain rules for the LAB subnet as well
#
############################################################################

# Allow port 913 for CIT's sidecar -- sidecar is actually a server process
# so incoming connections are expected.
sidecar_port="913"
iptables -A FORWARD -j ACCEPT -p tcp --source 132.236.0.0/16 --destination $hole_net --destination-port $sidecar_port
iptables -A FORWARD -j ACCEPT -p tcp --source 128.253.0.0/16 --destination $hole_net --destination-port $sidecar_port
iptables -A FORWARD -j ACCEPT -p tcp --source 132.236.0.0/16 --destination $lab_net --destination-port $sidecar_port
iptables -A FORWARD -j ACCEPT -p tcp --source 128.253.0.0/16 --destination $lab_net --destination-port $sidecar_port


# Actual kerberos authentication to the trusted authority (kerberos server)
# runs over UDP on these ports:
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos.cit.cornell.edu --source $hole_net --destination-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --source kerberos.cit.cornell.edu --destination $hole_net --source-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos.cit.cornell.edu --source $hole_net --destination-port kerberos
iptables -A FORWARD -j ACCEPT -p udp --source kerberos.cit.cornell.edu --destination $hole_net --source-port kerberos
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos.cit.cornell.edu --source $lab_net --destination-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --source kerberos.cit.cornell.edu --destination $lab_net --source-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos.cit.cornell.edu --source $lab_net --destination-port kerberos
iptables -A FORWARD -j ACCEPT -p udp --source kerberos.cit.cornell.edu --destination $lab_net --source-port kerberos
# Secondary kerberos server
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos2.cit.cornell.edu --source $hole_net --destination-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --source kerberos2.cit.cornell.edu --destination $hole_net --source-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos2.cit.cornell.edu --source $hole_net --destination-port kerberos
iptables -A FORWARD -j ACCEPT -p udp --source kerberos2.cit.cornell.edu --destination $hole_net --source-port kerberos
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos2.cit.cornell.edu --source $lab_net --destination-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --source kerberos2.cit.cornell.edu --destination $lab_net --source-port kerberos-iv
iptables -A FORWARD -j ACCEPT -p udp --destination kerberos2.cit.cornell.edu --source $lab_net --destination-port kerberos
iptables -A FORWARD -j ACCEPT -p udp --source kerberos2.cit.cornell.edu --destination $lab_net --source-port kerberos

###########################################################################
#
# Services enabled for the LAB subnet
#
###########################################################################

# SSH access to datura (only datura)
iptables -A FORWARD -j ACCEPT -p tcp --destination 128.253.40.10 --destination-port ssh
iptables -A FORWARD -j ACCEPT -p tcp --source 128.253.40.10 --source-port ssh
# NFS access to datura from solanine (for backing up datura's home)
iptables -A FORWARD -j ACCEPT -p udp --destination 128.253.40.10 --source 132.236.157.82
iptables -A FORWARD -j ACCEPT -p udp --source 128.253.40.10 --destination 132.236.157.82

# Allow UDP access to any port at the server below, for Colts II to function
# properly. Traffic analysis shows that it contacts a standard port (14010)
# first, then trys to contact again on a session-specific high udp port.
#
# I have just not bothered with more detailed rules and just allowed all ports
# so long as at our end its in high port space. Note that this rule is 
# bi-directional, and udp can be stateless which means this server, or
# anything masquerading as it (easy to do with connectionless udp) can send
# packets through the firewall. This is the reason we are restricting the 
# source port to high port space.
iptables -A FORWARD -j ACCEPT -p udp --source $lab_net --source-port 32768:65535 --destination carver.dataserver.cornell.edu
iptables -A FORWARD -j ACCEPT -p udp --destination $lab_net --destination-port 32768:65535 --source carver.dataserver.cornell.edu

# SNMP for querying printer status -- I have assigned printers high addresses
# counting down from 62 (highest usable)
# The mask can be increased a bit if necessary.
iptables -A FORWARD -j ACCEPT -p udp --source $hole_net --destination 128.253.40.60/30 --destination-port snmp
iptables -A FORWARD -j ACCEPT -p udp --destination $hole_net --source 128.253.40.60/30 --source-port snmp

# Lab systems use software licensed by Cornell's biotech facility, such as
# Sequencher and DNAStar -- these packages are enabled at runtime by a program
# called "keyserver" which verifies that the system using the software is
# authorized to do so. I connects to a server at biotech on via UDP, this
# is enabled below 
iptables -A FORWARD -j ACCEPT -p udp --source $lab_net --destination brcks.biotech.cornell.edu --destination-port 19283
iptables -A FORWARD -j ACCEPT -p udp --destination $lab_net --source brcks.biotech.cornell.edu --source-port 19283
iptables -A FORWARD -j ACCEPT -p udp --source $lab_net --destination brcks.biotech.cornell.edu --destination-port 5093
iptables -A FORWARD -j ACCEPT -p udp --destination $lab_net --source brcks.biotech.cornell.edu --source-port 5093

# Allow Rob to call us: 1720 is evidently a control port for gnomemeeting
/sbin/iptables -I FORWARD -j ACCEPT -p tcp --destination $hole_net --destination-port 1720 --source robbuels.dyndns.org
# Allow us to call Rob
/sbin/iptables -I FORWARD -j ACCEPT -p tcp --source $hole_net --destination robbuels.dyndns.org --destination-port 1720
# Allow gnomemeeting video back and forth.
/sbin/iptables -I FORWARD -j ACCEPT -p udp --destination $hole_net --destination-port 5000:5016 --source robbuels.dyndns.org
/sbin/iptables -I FORWARD -j ACCEPT -p udp --destination robbuels.dyndns.org --destination-port 5000:5016 --source $hole_net


# Clean this up maybe to reject pings but allow other icmp traffic?
iptables -I FORWARD -j ACCEPT -p icmp

# Finally, send everything else to the firewall
iptables -A INPUT  -m state --state NEW,INVALID -j firewall
iptables -A FORWARD -m state --state NEW,INVALID -j firewall
echo " done."
