#!/bin/sh
## Boot Script for firewall
#
# thanks and acknowledgements for examples and explanations to 
# barijaona 
# (see http://homepage.mac.com/barijaona/macintosh/osxpb4.html)
# daniel co^te'
# (http://www3.sympatico.ca/dccote/firewall.html)
# Dru Lavigne
# (http://www.onlamp.com/pub/a/bsd/2001/04/25/FreeBSD_Basics.html)
# and brian hill 
# (see http://personalpages.tds.net/~brian_hill/brickhouse.html), 
# I recommend brian's brickhouse for purchase if you're going to 
# do a lot of firewall configuration, it's a great product
# 
# Also see:
# http://www.macdevcenter.com/pub/a/mac/2002/12/27/macosx_firewall.html
# and
# http://www.securosis.com/blog/ipfw-rules-v20071212
# for additional information
#
# Finally, ipfw uses the /subnet mask denotation for declaring network ranges
# For example, 152.2.0.0/16 is the same as 152.2.0.0 with a 255.255.0.0, the 
# /16 means that 16 bits of the 32 possible bits are masked.
# Basically, the smaller the /index, the larger the range of 
# addresses encompassed
# This system is somewhat confusing to some folks, but there's a good online 
# subnet calculator you can use to figure out what ranges are covered 
# http://ccna.exampointers.com/subnet.htm
#
# 
# This version is designed to work with Timelox versions of ssh
# and TheHand, but will also work fine as a regular firewall. 
# See:
# https://wwwx.cs.unc.edu/~hays/dev/timelox_and_TheHand/
# for more information on timelox.
#
#
#
# 02/06/07   Updated to match standard startup scripts
# 11/29/09   Update for Leopard, refined some rules, back to stateful
#            inspection

. /etc/rc.common; # include the file with support for the service functions
 
########
# Set Variables
########

# Decide how to call ipfw (so you can run in test mode, etc, as you like)
IPFW="/sbin/ipfw -f";

# Set up a trusted hosts range
# These numbers represent the main CS networks at UNC
TrustedHosts="152.2.128.0/20, 204.85.191.0/24, 10.2.128.0/20, 192.168.243.0/24, 172.29.166.0/24";

# Set up a range of hosts you trust somewhat, but not so much
# In this example, we're looking at the main unc.edu subnets
NotSoTrustedHosts="152.2.0.0/16, 152.19.0.0/16, 152.23.0.0/16";

# If you use the same DHCP servers all of the time, set them here,
# else just leave this line commented out.
DCHP_SERVERS="152.2.131.227, 152.2.131.227";
   
 StartService ()
   {
   echo "Starting Firewall"

   ########
   # Enable Logging
   ########
   #
   # Logged entries go into /var/log/system.log
   # But there's no point in logging unless you're going to check the 
   # entries. In this script, all deny are tagged with a log 
   
   # To disable logging, comment out the following 
   # three lines and uncomment the fourth:
   if [ `/usr/sbin/sysctl -n net.inet.ip.fw.verbose` == 0 ] ; then
         /usr/sbin/sysctl -w net.inet.ip.fw.verbose=1
   fi
   #/usr/sbin/sysctl -w net.inet.ip.fw.verbose=0
   
   # Set some vars for firewall parameters, these are close to stock
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_max=8192 > /dev/null;
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_buckets=512 > /dev/null;
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_ack_lifetime=300 > /dev/null;
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_syn_lifetime=20 > /dev/null;
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_fin_lifetime=5 > /dev/null;
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_rst_lifetime=5> /dev/null;
   /usr/sbin/sysctl -w net.inet.ip.fw.dyn_short_lifetime=10 > /dev/null;
   # This sets a limit to the number of log events for a given rule
   /usr/sbin/sysctl -w net.inet.ip.fw.verbose_limit=100 > /dev/null;
   
   ########
   # Flush
   ########
   
   # Purge existing rules, this blanks any existing rules
   ${IPFW} flush;
   
   ########
   # Localhost Settings
   ########
   
   # User verify reverse path to stop spoofed packets
   ${IPFW} add deny log ip from any to any not verrevpath in;
   
   # Allow everything on the localhost (127.0.0.1)
   # This way the machine can connect to itself via the localhost interface
   ${IPFW} add allow ip from me to me;
   
   # Now check for spoofing attacks via localhost and source routed
   # deny and log these packets
   ${IPFW} add deny log ip from 127.0.0.0/8 to any in;
   ${IPFW} add deny log ip from any to 127.0.0.0/8 in;
   ${IPFW} add deny log ip from any to any ipoptions ssrr,lsrr in;
   ${IPFW} add deny log tcp from any to any frag;
   
   ########
   # Multicast rules
   ########
   
   # Deny tcp packets sent to multicast 
   # (that makes some sense as multicasts are UDP), so
   # we shouldn't see any tcp packets coming to multicast addies.
   ${IPFW} add deny log tcp from any to 224.0.0.0/3 in;
   
   # If you're using ${TrustedHosts} or ${NotSoTrustedHosts}
   # you can allow multicast from these networks as well.
   ${IPFW} add allow ip from ${TrustedHosts} to 224.0.0.0/3 in;
   
   # Or, deny all multicasts in 
   # For most users this is fine, but it will disable some media software
   # and some CIFS server functions
   #${IPFW} add deny log ip from 224.0.0.0/3 to any in;
   
   # This one blocks scanning for port 0 to see if machine is there 
   ${IPFW} add deny tcp from any to any 0 in;

   ########
   # Set up stateful firewall
   ########
   ${IPFW} add check-state;
   # Allow all outbound and start the connection tracker.
   # Any connections started from this machine will be tracked
   # and replies back allowed.
   ${IPFW} add allow tcp from me to any keep-state;
   ${IPFW} add allow udp from me to any keep-state;
   # This will block any packets that are stealthed using 
   # a syn/ack instead of a syn. Also, we're setting a high numbered 
   # rule number here to create a space for thehand and timelox, 
   # see:
   # https://wwwx.cs.unc.edu/~hays/dev/timelox_and_TheHand/
   # for more information on this
   ${IPFW} add 25000 deny tcp from any to any established;
   
   ########
   # Minimal Requirements
   ########
   
   # Stateful firewalls in tiger and leopard don't play well with DHCP
   # Use this rule with laptops that move from net to net.
   ${IPFW} add allow udp from any to any src-port 67 dst-port 68 in;
   # Or, if you know what DHCP servers you should be using, use a specific
   # rule. This is better since there are some malware packages that 
   # infect a machine with a dhcp server and serve up bad dns server 
   # information to set up man in the middle attacks. This uses the variable
   # higher up so make sure you set the server values there.
   #${IPFW} add allow udp from ${DCHP_SERVERS} to any src-port 67 dst-port 68 in;
   
   
   # Trusted Hosts, this allows all traffic from the hosts we trust
   ${IPFW} add allow ip from ${TrustedHosts} to any in; 
   
   ########
   # ICMP
   ########
   
   # Allow outbound icmp
   ${IPFW} add allow icmp from any to any out; 
   
   # If you want to allow anyone to ping you, or run a tracroute to you
   # uncomment this
   #${IPFW} add allow icmp from any to any in;
   
   # This is more secure, allows ICMP (ping and traceroute) from 
   # the not so trusted hosts range
   # This will help your IT folks troubleshoot problems
   #${IPFW} add allow icmp from ${TrustedHosts} to any in;
   ${IPFW} add allow icmp from ${NotSoTrustedHosts} to any in;
   
   # This lets this machine receive ping replies and 
   # the icmp errors that traceroute depends upon, but doesn't 
   # allow you to be pinged or tracerouted.
   ${IPFW} add allow icmp from any to me icmptypes 0,3,11 in 
   
   ########
   # Services
   ########
   
   # Don't open these unless you want to run the service.
   # Also consider who would need access, for example, it's very unlikely 
   # you'll need to allow ssh from the entire internet. But most
   # folks want the web server wide open
   #
   # Most of these are set up such that it's the ${NotSoTrustedHosts} range
   # to which a service is open. Generally, ${TrustedHosts} are already
   # allow to connect to all ports
      
   # Allow web service from anywhere
   ${IPFW} add allow tcp from any to any 80;
   ${IPFW} add allow tcp from any to any 443;
   
   # SSH
   ${IPFW} add allow tcp from ${NotSoTrustedHosts} to any 22 in;
   # If you want to open ssh to everyone, use this.
   #${IPFW} add allow tcp from any to any 22 in;
   
   # AppleShare File Sharing   
   ${IPFW} add allow tcp from ${NotSoTrustedHosts} to any 548 in;
   ${IPFW} add allow tcp from ${NotSoTrustedHosts} to any 427 in;
   
   # SMB/CIFS (windows networking)
   ${IPFW} add allow ip from ${NotSoTrustedHosts} to any 137-139 in;
   
   # LDAP (in case you run an ldap server)
   #${IPFW} add  allow tcp from ${NotSoTrustedHosts} to any 389 in;
   #${IPFW} add  allow udp from ${NotSoTrustedHosts} to any 389 in;
      
   # Quicktime Streaming Service 
   # Allow QTSS from anywhere
   #${IPFW} add allow tcp from any to any 545 in;
   # Allow RTSP from anywhere (part of QTSS)
   #${IPFW} add allow tcp from any to any 554 in;
   # Allow UDP RTSP data from any where
   #${IPFW} add allow udp from any to any 6970-6999 in ;
      
   # iTunes 
   # Allow iTunes sharing from unc.edu addresses
   ${IPFW} add  allow tcp from ${TrustedHosts} to any 3689 in;
   
   # Allow Rendevous, aka Bonjour, aka mDNS
   ${IPFW} add allow ip from ${TrustedHosts} to any 5353 in;
   ${IPFW} add allow udp from ${TrustedHosts} 5353 to any dst-port 1024-65535 in
   
   #######
   # Closing up
   #######
   
   # Block and log all ip packets not matched by a prior rule
   # so basically we're defaulting to deny rather than accept
   # In terms of udp reject is stealthier
   # since the way you scan for UDP ports is to look for ports that
   # don't send you an error on connect
   ${IPFW} add 65000 reject udp from any to any in; 
   ${IPFW} add deny icmp from any to any in;   
   ${IPFW} add deny ip from any to any in;

} # end of StartService

StopService ()
   {
   ${IPFW} flush;
   ERROR_NUMBER=${?};
   if [[ ${ERROR_NUMBER} == "0" ]] 
   then 
      ConsoleMessage "Firewall has been stopped";
   else
      ConsoleMessage "There was a problem stopping the Firewall";
      exit 1;
   fi
   }

RestartService ()
   {
   StopService
   StartService
   }
   
RunService "${1:-start}";

