#!/bin/sh
# Based on an example Copyright (c) 1996  Poul-Henning Kamp,
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD: src/etc/rc.firewall,v 1.30.2.16 2003/02/10 05:45:06 trhodes Exp $
#

#
# Setup system for firewall service for a DHCP client, before it makes
# contact with a DCHP server.
#

dir="/etc"
seg_bcast="255.255.255.255"
bcast=""
ip=""
mask=""
net=""
gateway=""

# Get comamnd-line arguments first
while getopts "b:d:g:i:m:n:t" flag
do
  case $flag in
  b)		# broadcast address
	bcast="${OPTARG}"
	;;
  d)		# DHCP server
	dhcpserver="${OPTARG}"
	;;
  g)		# my gateway's IP address
	gateway="${OPTARG}"
	;;
  i)		# my IP address
	ip="${OPTARG}"
	;;
  m)		# my subnet mask
	mask="${OPTARG}"
	;;
  n)		# my netwrk number
	net="${OPTARG}"
	;;
  t)		# test mode
	firewall_test="YES"
	dir="."
	;;
  *)		# error; usage message and exit
	exit 1
	;;
  esac
done

shift $(($OPTIND - 1))

# Suck in the configuration variables.
if [ -z "${source_rc_confs_defined}" ]; then
	if [ -r ${dir}/defaults/rc.conf ]; then
		. ${dir}/defaults/rc.conf
		source_rc_confs
	elif [ -r ${dir}/rc.conf ]; then
		. ${dir}/rc.conf
	fi
fi

if [ -n "${1}" ]; then
	firewall_type="${1}"
fi

############
# Set quiet mode if requested
#
case ${firewall_quiet} in
[Yy][Ee][Ss])
	fwcmd="/sbin/ipfw -q"
	tblcmd="/usr/local/sbin/mk_table -f"
	;;
*)
	fwcmd="/sbin/ipfw"
	tblcmd="/usr/local/sbin/mk_table -f -v"
	;;
esac

# Set test mode if requested
if [ "x$firewall_test" = "xYES" ]; then
	echo "Test mode"
	fwcmd="echo ${fwcmd}"
	tblcmd="${tblcmd} -t"
fi

error=""
if [ -z "${bcast}" ]; then
   error="${error}
     Need '-b broadcast_address'"
fi
if [ -z "${ip}" ]; then
   error="${error}
     Need '-i ip_address'"
fi
if [ -z "${mask}" ]; then
   error="${error}
     Need '-m netmask'"
fi
#if [ -z "${net}" ]; then
#   error="${error}
#     Need '-n network_number'"
#fi
if [ -z "${gateway}" ]; then
   error="${error}
     Need '-r gateway_address'"
fi
if [ -n "${error}" ] ; then
  echo "${error}"
  exit 2
fi

setup_loopback () {
	############
	# Only in rare cases do you want to change these rules
	#
	${fwcmd} add 100 pass all from any to any via lo0
	${fwcmd} add 200 deny all from any to 127.0.0.0/8
	${fwcmd} add 300 deny ip from 127.0.0.0/8 to any
}

############
# Flush out the list before we begin.
#
${fwcmd} -f flush

setup_loopback

# Allow all traffic that is both from and to me
${fwcmd} add pass ip from ${ip} to ${ip}

# Block packets with IP options set
${fwcmd} add deny log ip from any to any ipoptions rr
${fwcmd} add deny log ip from any to any ipoptions ts
${fwcmd} add deny log ip from any to any ipoptions ssrr
${fwcmd} add deny log ip from any to any ipoptions lsrr

# Block fragments
${fwcmd} add deny log all from any to any frag

# Certain netblocks appear to be troublesome.  Block them.
# Note: we use IPFW tables for this.  Data resides in /var/ipfw.
# Also, we merely set up the rules here.  We populate the tables
# below, after all of the IPFW rules are in place.
${fwcmd} add ${rnum} deny log all from table\(1\) to ${ip}
${fwcmd} add ${rnum} deny log all from ${ip} to table\(1\)
${fwcmd} add ${rnum} deny log all from table\(2\) to ${ip} 22
${fwcmd} add ${rnum} deny log all from table\(3\) to ${ip} 80,443

# Drop certain unwanted traffic silently
${fwcmd} add deny udp from any 135-139 to any
${fwcmd} add deny udp from any to any 135-139
${fwcmd} add deny tcp from any 135-139 to any
${fwcmd} add deny tcp from any to any 135-139
${fwcmd} add deny udp from any 445 to any
${fwcmd} add deny udp from any to any 445
${fwcmd} add deny tcp from any 445 to any
${fwcmd} add deny tcp from any to any 445
${fwcmd} add deny udp from any to any 631
${fwcmd} add deny udp from any to any 1985
${fwcmd} add deny udp from any to any 2222
${fwcmd} add deny udp from any to any 5353
${fwcmd} add deny ip from 224.0.0.0/4 to any
${fwcmd} add deny ip from any to 224.0.0.0/4

# Allow selected ICMP traffic
${fwcmd} add pass icmp from any to any icmptypes 0,3,4,8,11,12

# Permit us to send DHCP traffic between us and our router or DHCP server,
# but don't listen to any broadcasts, and don't send other broadcasts
${fwcmd} add pass udp from ${ip} 68 to ${gateway} 67 keep-state
${fwcmd} add pass udp from ${gateway} 67 to ${ip} 68 keep-state
if [ -n "${dhcpserver}" ]; then
  ${fwcmd} add pass udp from ${ip} 68 to ${dhcpserver} 67 keep-state
  ${fwcmd} add pass udp from ${dhcpserver} 67 to ${ip} 68 keep-state
fi
# Except that we do want to be able to configure the Apple AirPort:
${fwcmd} add pass udp from ${ip} to ${bcast} 192 keep-state
${fwcmd} add pass udp from any 192 to ${ip}
# And certain other, SNMP-managed, devices:
${fwcmd} add pass udp from ${ip}:${mask} 162 to ${bcast} 162 keep-state
# NOW block other broadcasts...
${fwcmd} add deny all from any to ${bcast}
${fwcmd} add deny all from ${bcast} to any

# Allow TCP through if setup succeeded
${fwcmd} add pass tcp from any to any established

# Allow setup of outgoing TCP connections
${fwcmd} add pass tcp from ${ip} to any setup

# Allow SSH access
${fwcmd} add pass log tcp from any to any 22 setup

# Allow access to the local Web server
${fwcmd} add pass tcp from any to ${ip} 80 setup
${fwcmd} add pass tcp from any to ${ip} 443 setup

# Disallow setup of all other TCP connections
${fwcmd} add deny log tcp from any to any setup

# Allow DNS queries out in the world
${fwcmd} add pass udp from ${ip} to any 53 keep-state

# Allow NTP queries out in the world
${fwcmd} add pass udp from ${ip} to any 123 keep-state
# And NTP chimes might be broadcast
${fwcmd} add pass udp from any 123 to ${seg_bcast} 123 keep-state

# Actually, we want to allow UDP from me in general....
${fwcmd} add pass udp from ${ip} to any keep-state

# Everything else is denied by default, unless the
# IPFIREWALL_DEFAULT_TO_ACCEPT option is set in your kernel
# config file.

# But we add another "deny/log" rule, so we can see what gets blocked
${fwcmd} add deny log all from any to any

# OK; now we populate the tables:
${tblcmd} /var/ipfw
