--- /dev/null
+*.sh
+cruft
--- /dev/null
+### Makefile for firewall scripts
+
+MAIN_M4_SOURCES =
+HOSTS =
+
+###--------------------------------------------------------------------------
+### Local configuration.
+
+## Should set up HOSTS and add stuff to MAIN_M4_SOURCES if necessary.
+include local.mk
+
+###--------------------------------------------------------------------------
+### Configuration.
+
+## The main m4 inputs which construct the firewall. These are read in last
+## to allow local configuration to change their environments.
+MAIN_M4_SOURCES += config.m4
+MAIN_M4_SOURCES += prologue.m4
+MAIN_M4_SOURCES += functions.m4
+MAIN_M4_SOURCES += numbers.m4
+MAIN_M4_SOURCES += bookends.m4
+MAIN_M4_SOURCES += classify.m4
+MAIN_M4_SOURCES += icmp.m4
+
+## All of our m4 inputs. The base gets read first to set things up.
+M4_SOURCES = base.m4
+M4_SOURCES += $(MAIN_M4_SOURCES)
+
+###--------------------------------------------------------------------------
+### Hosts.
+
+TARGETS = $(addsuffix .sh,$(HOSTS))
+
+###--------------------------------------------------------------------------
+### Building.
+
+all: $(TARGETS)
+
+%.sh: %.m4 $(M4_SOURCES)
+ m4 -P base.m4 $*.m4 $(MAIN_M4_SOURCES) >$@.new
+ chmod +x $@.new
+ mv $@.new $@
+
+clean:; rm -f $(TARGETS) *.new
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+m4_divert(-1)
+### -*-m4-*-
+###
+### Failsafe prologue for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_changequote(<:, :>)
+m4_changecom(<:##:>)
+
+###--------------------------------------------------------------------------
+### Overall structure.
+###
+### 0 File header: shebang, do-not-edit warning. [base]
+### 5 Configuration. [config]
+### 10 Prologue: command-line parsing and failsafe. [prologue]
+### 20 Function definitions. [functions]
+### 25 Port numbers etc. [numbers]
+### 30 Initialization. [bookends]
+### 30 Clear existing rules. [bookends]
+### 32 Set safe IP options. [bookends]
+### 34 Error chains. [bookends]
+### 36 Give loopback traffic a free pass. [bookends]
+### 40 Address classification. [classify]
+### 42 Definition of address class policies. [local]
+### 44 Definition of interfaces and addresses. [local]
+### 46 Handling of default interface. [classify]
+### 50 ICMP filtering. [icmp]
+### 52 Local configuration. [local]
+### 58 Finally accept ICMP, hook onto INPUT and FORWARD. [icmp]
+### 60 Local configuration. [local]
+### 90 Finishing touches. [bookends]
+### 94 Set final policies. [bookends]
+### 99 File footer: do-not-edit warning. [base]
+
+###--------------------------------------------------------------------------
+### Headers and footers.
+
+m4_divert(0)m4_dnl
+#! /bin/sh
+### *** GENERATED FILE: DO NOT EDIT ***
+
+set -e
+PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
+
+m4_divert(99)m4_dnl
+### *** GENERATED FILE: DO NOT EDIT ***
+m4_divert(-1)
+
+###--------------------------------------------------------------------------
+### Unpleasant m4 hacking.
+
+## dolist(VAR, LIST, BODY)
+##
+## LIST is a parenthesized list of comma-separated items. For each item,
+## set VAR to expand to the item and emit the BODY.
+m4_define(<:dolist:>, <:m4_pushdef(<:$1:>)__loop($@)m4_popdef(<:$1:>):>)
+m4_define(<:__loop:>, <:m4_ifelse(<:$2:>, <:():>, ,m4_dnl
+<:m4_define(<:$1:>, __first$2)$3<::>__loop(<:$1:>,(m4_shift$2),<:$3:>):>):>)
+m4_define(<:__first:>, <:$1:>)
+
+## split(DELIM, TEXT)
+##
+## Split TEXT at characters in DELIM; stash result in positional parameters.
+m4_define(<:split:>, <:IFS=$1; set -- $2; IFS=$STDIFS:>)
+
+## defconf(CONF, DEFAULT)
+##
+## Define config variable CONF, assigning it the DEFAULT value if not
+## overridden by setconf.
+m4_define(<:defconf:>, <:: ${$1=m4_ifdef(<:conf_$1:>, conf_$1, $2)}:>)
+
+## setconf(CONF, VALUE)
+##
+## Set config variable VALUE.
+m4_define(<:setconf:> <:m4_define(<:conf_$1:>, <:$2:>):>)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Initialization and finishing touches for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(30)m4_dnl
+###--------------------------------------------------------------------------
+### Clear existing firewall rules.
+
+## The main chains: set policy to drop, and then clear the rules. For a
+## while, incoming packets will be silently dropped, but we should have got
+## everything going before anyone actually hits a timeout.
+for t in mangle filter; do
+ for i in PREROUTING INPUT FORWARD OUTPUT POSTROUTING; do
+ run iptables -t $t -P $i DROP 2>/dev/null || :
+ run iptables -t $t -F $i 2>/dev/null || :
+ done
+ run iptables -t $t -F
+ run iptables -t $t -X
+done
+
+m4_divert(32)m4_dnl
+###--------------------------------------------------------------------------
+### Set safe IP options.
+
+## Set forwarding options. Apparently setting ip_forward clobbers other
+## settings, so put this first.
+setopt ip_forward $forward
+setdevopt forwarding $forward
+
+## Set dynamic port allocation.
+setopt ip_local_port_range $open_port_min $open_port_max
+
+## Deploy SYN-cookies if necessary.
+setopt tcp_syncookies 1
+
+## Turn on the reverse-path filter, and log weird things.
+setdevopt rp_filter 1
+setdevopt log_martians 1
+
+## Turn off things which can mess with our routing decisions.
+setdevopt accept_source_route 0
+setdevopt accept_redirects 0
+
+## If we're maent to stop the firewall, then now is the time to do it.
+$exit_after_clearing
+
+m4_divert(34)m4_dnl
+###--------------------------------------------------------------------------
+### Establish error chains.
+
+errorchain forbidden REJECT --reject-with icmp-host-prohibited
+## Generic `not allowed' chain. Rejects with ICMP host-prohibited.
+
+errorchain tcp-fragment REJECT --reject-with icmp-host-prohibited
+## Chain for logging fragmented TCP segements. Rejects with ICMP
+## host-prohibited.
+
+errorchain bad-tcp REJECT -p tcp --reject-with tcp-reset
+## Bad TCP segments (e.g., for unknown connections). Sends a TCP reset.
+
+errorchain mangle:bad-source-address DROP
+## Packet arrived on wrong interface for its source address. Drops the
+## packet, since there's nowhere sensible to send an error.
+
+errorchain interesting ACCEPT
+## Not an error, just log interesting packets.
+
+m4_divert(36)m4_dnl
+###--------------------------------------------------------------------------
+### Don't clobber local traffic.
+
+run iptables -A INPUT -i lo -j ACCEPT
+
+m4_divert(90)m4_dnl
+###--------------------------------------------------------------------------
+### Finishing touches.
+
+m4_divert(94)m4_dnl
+## Locally generated packets are all OK.
+run iptables -P OUTPUT ACCEPT
+
+## Other incoming things are forbidden.
+for chain in INPUT FORWARD; do
+ run iptables -A $chain -g forbidden
+done
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Initialization and finishing touches for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(40)m4_dnl
+###--------------------------------------------------------------------------
+### Address classification.
+###
+### The objective of address classification is to work out what kind of
+### networks a packet is travelling between, in order to make filtering
+### decisions easier.
+###
+### Address classification is done in the mangle table, by attaching
+### appropriate marks to the packet. We split the Internet into a number of
+### address classes, and make forwarding decisions based on the classes of
+### the source and destination addresses.
+###
+### The mark word is split into three fields: the FROM and TO fields simply
+### record the source and destination classes numerically; the MASK field is
+### used to determine whether forwarding should occur. There is a mask bit
+### for each address class. Source classification sets mask bits according
+### to the forwarding policy for the source address class. Destination
+### classification clears all of the mask bits except for the one
+### corresponding to the actual destination class. Therefore, forwarding is
+### permitted if and only if the mask bits are not all zero.
+###
+### The mangle chains are arranged as follows.
+###
+### The PREROUTING hook simply invokes in-classify and out-classify chains as
+### subroutines. These will tail-call appropriate classification chains.
+###
+### The in-classify chain is responsible for both source address
+### classification and verifying that the packet arrived from the correct
+### interface. It does an initial dispatch on the source interface, to
+### in-IFACE. The in-IFACE chain dispatches to mark-from-CLASS when it
+### recognizes an address belonging to the CLASS; if no matches succeed, it
+### goes to bad-source-address, which logs a message and drops the packet.
+### The default interface is special. If no explicit matches are found, it
+### dispatches to in-default which forbids a few obviously evil things and
+### finally dispatches to mark-from-untrusted.
+###
+### The out-classify is simpler because it doesn't care about the interface.
+### It simply checks each network range in turn, dispatching to mark-to-CLASS
+### on a match or mark-to-DEFAULT (probably untrusted) if there is no match.
+
+clearchain mangle:in-classify mangle:in-default mangle:out-classify
+clearchain mangle:local-source
+
+## Packets over the loopback interface are automatically trusted. All manner
+## of weird stuff happens on lo, and it's best not to second-guess it.
+run iptables -t mangle -A in-classify -i lo -j ACCEPT
+
+## Local bootp packets have bizarre addresses. Don't block them just because
+## of this.
+run iptables -t mangle -A in-classify -j RETURN \
+ -s 0.0.0.0 -d 255.255.255.255 \
+ -p udp --source-port $port_bootpc --destination-port $port_bootps
+
+## Since packets with source and destination addresses both local will go
+## over the loopback interface, I shouldn't see a packet from me over any
+## other interface. Except that I will if I sent a broadcast or multicast.
+## Allow the broadcasts, and remember not to trust them.
+run iptables -t mangle -A local-source -j RETURN \
+ -m addrtype --dst-type BROADCAST
+run iptables -t mangle -A local-source -j RETURN \
+ -m addrtype --dst-type MULTICAST
+run iptables -t mangle -A local-source -g bad-source-address
+run iptables -t mangle -A in-classify -j local-source \
+ -m addrtype --src-type LOCAL
+
+m4_divert(41)m4_dnl
+## Define the important networks.
+for pass in 1 2; do
+ netclassindex=0
+m4_divert(42)m4_dnl
+done
+
+m4_divert(46)m4_dnl
+## Mark addresses reachable on non-default interfaces as not reachable on the
+## default interface.
+trace "nets = $allnets"
+for net in $allnets; do
+ case $net in
+ "$defaultiface":*)
+ ;;
+ *)
+ run iptables -t mangle -A in-$defaultiface \
+ -s ${net#*:} -g bad-source-address
+ ;;
+ esac
+done
+
+## Fill in the black holes in the network.
+for addr in \
+ 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 \
+ 127.0.0.0/8 192.0.2.0/24
+do
+ run iptables -t mangle -A in-default -s $addr -g bad-source-address
+done
+
+m4_divert(92)m4_dnl
+## Put the final default decision on the in-default chain, and attach the
+## classification chains to the PREROUTING hook.
+run iptables -t mangle -A in-$defaultiface -g mark-from-$defaultclass
+run iptables -t mangle -A PREROUTING -j in-classify
+run iptables -t mangle -A PREROUTING -j out-classify
+
+## Now it's safe to let stuff through.
+for i in PREROUTING INPUT FORWARD OUTPUT POSTROUTING; do
+ run iptables -t mangle -P $i ACCEPT
+done
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Configuration for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(5)m4_dnl
+###--------------------------------------------------------------------------
+### Configuration.
+
+## Name of this script.
+defconf(firewall_script, /etc/init.d/firewall)
+
+## Name of emergency fallback sceipt.
+defconf(firewall_failsafe, /etc/init.d/firewall.safe)
+
+## Set the range of dynamically allocated ports. Access to these from
+## outside is permitted.
+defconf(open_port_min, 32000)
+defconf(open_port_max, 54999)
+
+## Whether to permit forwarding.
+defconf(forward, 1)
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Main packet filtering
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(60)m4_dnl
+###--------------------------------------------------------------------------
+### Main packet filtering.
+
+## Incoming packets from untrusted sources need special inspection.
+clearchain inbound
+run iptables -A INPUT -m mark --mark $from_untrusted/$MASK_FROM -g inbound
+
+## Locally generated packets are all OK.
+run iptables -P OUTPUT ACCEPT
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Utility functions for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(20)m4_dnl
+###--------------------------------------------------------------------------
+### Utility functions.
+
+## doit COMMAND ARGS...
+##
+## If debugging, print the COMMAND and ARGS. If serious, execute them.
+run () {
+ set -e
+ if [ "$FW_DEBUG" ]; then echo "* $*"; fi
+ if ! [ "$FW_NOACT" ]; then "$@"; fi
+}
+
+## trace MESSAGE...
+##
+## If debugging, print the MESSAGE.
+trace () {
+ set -e
+ if [ "$FW_DEBUG" ]; then echo "$*"; fi
+}
+
+## defport NAME NUMBER
+##
+## Define $port_NAME to be NUMBER.
+defport () {
+ name=$1 number=$2
+ eval port_$name=$number
+}
+
+m4_divert(22)m4_dnl
+###--------------------------------------------------------------------------
+### Basic chain constructions.
+
+## clearchain CHAIN CHAIN ...
+##
+## Ensure that the named chains exist and are empty.
+clearchain () {
+ set -e
+ for chain; do
+ case $chain in
+ *:*) table=${chain%:*} chain=${chain#*:} ;;
+ *) table=filter ;;
+ esac
+ run iptables -t $table -N $chain
+ done
+}
+
+## errorchain CHAIN ACTION ARGS ...
+##
+## Make a chain which logs a message and then invokes some other action,
+## typically REJECT. Log messages are prefixed by `fw: CHAIN'.
+errorchain () {
+ set -e
+ chain=$1; shift
+ case $chain in
+ *:*) table=${chain%:*} chain=${chain#*:} ;;
+ *) table=filter ;;
+ esac
+ clearchain $table:$chain
+ run iptables -t $table -A $chain -j LOG \
+ -m limit --limit 3/minute --limit-burst 10 \
+ --log-prefix "new fw: $chain " --log-level notice
+ run iptables -t $table -A $chain -j "$@"
+}
+
+m4_divert(24)m4_dnl
+###--------------------------------------------------------------------------
+### Basic option setting.
+
+## setopt OPTION VALUE
+##
+## Set an IP sysctl.
+setopt () {
+ set -e
+ opt=$1; shift; val=$*
+ run sysctl -q net/ipv4/$opt="$val"
+}
+
+## setdevopt OPTION VALUE
+##
+## Set an IP interface-level sysctl.
+setdevopt () {
+ set -e
+ opt=$1; shift; val=$*
+ for i in /proc/sys/net/ipv4/conf/*; do
+ [ -f $i/$opt ] &&
+ run sysctl -q net/ipv4/conf/${i#/proc/sys/net/ipv4/conf/}/$opt="$val"
+ done
+}
+
+m4_divert(26)m4_dnl
+###--------------------------------------------------------------------------
+### Packet filter construction.
+
+## conntrack CHAIN
+##
+## Add connection tracking to CHAIN, and allow obvious stuff.
+conntrack () {
+ set -e
+ chain=$1
+ run iptables -A $chain -p tcp -m state \
+ --state ESTABLISHED,RELATED -j ACCEPT
+ run iptables -A $chain -p tcp ! --syn -g bad-tcp
+}
+
+## allowservices CHAIN PROTO SERVICE ...
+##
+## Add rules to allow the SERVICES on the CHAIN.
+allowservices () {
+ set -e
+ chain=$1 proto=$2; shift 2
+ count=0
+ list=
+ for svc; do
+ case $svc in
+ *:*)
+ n=2
+ left=${svc%:*} right=${svc#*:}
+ case $left in *[!0-9]*) eval left=\$port_$left ;; esac
+ case $right in *[!0-9]*) eval right=\$port_$right ;; esac
+ svc=$left:$right
+ ;;
+ *)
+ n=1
+ case $svc in *[!0-9]*) eval svc=\$port_$svc ;; esac
+ ;;
+ esac
+ case $svc in
+ *: | :* | "" | *[!0-9:]*)
+ echo >&2 "Bad service name"
+ exit 1
+ ;;
+ esac
+ count=$(( $count + $n ))
+ if [ $count -gt 15 ]; then
+ run iptables -A $chain -p $proto -m multiport -j ACCEPT \
+ --destination-ports ${list#,}
+ list= count=$n
+ fi
+ list=$list,$svc
+ done
+ case $list in
+ "")
+ ;;
+ ,*,*)
+ run iptables -A $chain -p $proto -m multiport -j ACCEPT \
+ --destination-ports ${list#,}
+ ;;
+ *)
+ run iptables -A $chain -p $proto -j ACCEPT \
+ --destination-port ${list#,}
+ ;;
+ esac
+}
+
+## ntpclient CHAIN NTPSERVER ...
+##
+## Add rules to CHAIN to allow NTP with NTPSERVERs.
+ntpclient () {
+ set -e
+ chain=$1; shift
+ for ntp; do
+ run iptables -A $chain -s $ntp -j ACCEPT \
+ -p udp --source-port 123 --destination-port 123
+ done
+}
+
+## dnsresolver CHAIN
+##
+## Add rules to allow CHAIN to be a DNS resolver.
+dnsresolver () {
+ set -e
+ chain=$1
+ for p in tcp udp; do
+ run iptables -A $chain -j ACCEPT \
+ -m state --state ESTABLISHED \
+ -p $p --source-port 53
+ done
+}
+
+## openports CHAIN [MIN MAX]
+##
+## Add rules to CHAIN to allow the open ports.
+openports () {
+ set -e
+ chain=$1; shift
+ [ $# -eq 0 ] && set -- $open_port_min $open_port_max
+ run iptables -A $chain -p tcp -g interesting --destination-port $1:$2
+ run iptables -A $chain -p udp -g interesting --destination-port $1:$2
+}
+
+m4_divert(28)m4_dnl
+###--------------------------------------------------------------------------
+### Packet classification.
+
+## defbitfield NAME WIDTH
+##
+## Defines MASK_NAME and BIT_NAME symbolic constants for dealing with
+## bitfields: x << BIT_NAME yields the value x in the correct position, and
+## ff & MASK_NAME extracts the corresponding value.
+defbitfield () {
+ set -e
+ name=$1 width=$2
+ eval MASK_$name=$(( (1 << $width) - 1 << $bitindex ))
+ eval BIT_$name=$bitindex
+ bitindex=$(( $bitindex + $width ))
+}
+
+## Define the layout of the bitfield.
+bitindex=0
+defbitfield MASK 16
+defbitfield FROM 4
+defbitfield TO 4
+
+## defnetclass NAME FORWARD-TO...
+##
+## Defines a netclass called NAME, which is allowed to forward to the
+## FORWARD-TO netclasses.
+##
+## For each netclass, constants from_NAME and to_NAME are defined as the
+## appropriate values in the FROM and TO fields (i.e., not including any mask
+## bits).
+##
+## This function also establishes mangle chains mark-from-NAME and
+## mark-to-NAME for applying the appropriate mark bits to the packet.
+##
+## Because it needs to resolve forward references, netclasses must be defined
+## in a two-pass manner, using a loop of the form
+##
+## for pass in 1 2; do netclassindex=0; ...; done
+netclassess=
+defnetclass () {
+ set -e
+ name=$1; shift
+ case $pass in
+ 1)
+
+ ## Pass 1. Establish the from_NAME and to_NAME constants, and the
+ ## netclass's mask bit.
+ eval from_$name=$(( $netclassindex << $BIT_FROM ))
+ eval to_$name=$(( $netclassindex << $BIT_TO ))
+ eval _mask_$name=$(( 1 << ($netclassindex + $BIT_MASK) ))
+ nets="$nets $name"
+ ;;
+ 2)
+
+ ## Pass 2. Compute the actual from and to values. We're a little bit
+ ## clever during source classification, and set the TO field to
+ ## all-bits-one, so that destination classification needs only a single
+ ## AND operation.
+ from=$(( ($netclassindex << $BIT_FROM) + (0xf << $BIT_TO) ))
+ for net; do
+ eval bit=\$_mask_$net
+ from=$(( $from + $bit ))
+ done
+ to=$(( ($netclassindex << $BIT_TO) + \
+ (0xf << $BIT_FROM) + \
+ (1 << ($netclassindex + $BIT_MASK)) ))
+ trace "from $name --> set $(printf %x $from)"
+ trace " to $name --> and $(printf %x $from)"
+
+ ## Now establish the mark-from-NAME and mark-to-NAME chains.
+ clearchain mangle:mark-from-$name mangle:mark-to-$name
+ run iptables -t mangle -A mark-from-$name -j MARK --set-mark $from
+ run iptables -t mangle -A mark-to-$name -j MARK --and-mark $to
+ ;;
+ esac
+ netclassindex=$(( $netclassindex + 1 ))
+}
+
+## defiface NAME NETCLASS:NETWORK/MASK...
+##
+## Declares a network interface NAME and associates with it a number of
+## reachable networks. During source classification, a packet arriving on
+## interface NAME from an address in NETWORK/MASK is classified as coming
+## from to NETCLASS. During destination classification, all packets going to
+## NETWORK/MASK are classified as going to NETCLASS, regardless of interface
+## (which is good, because the outgoing interface hasn't been determined
+## yet).
+##
+## As a special case, the NETWORK/MASK can be the string `default', which
+## indicates that all addresses not matched elsewhere should be considered.
+ifaces=:
+defaultiface=none
+allnets=
+defiface () {
+ set -e
+ name=$1; shift
+ case $ifaces in
+ *:"$name":*) ;;
+ *)
+ clearchain mangle:in-$name
+ run iptables -t mangle -A in-classify -i $name -g in-$name
+ ;;
+ esac
+ ifaces=$ifaces$name:
+ for item; do
+ netclass=${item%:*} addr=${item#*:}
+ case $addr in
+ default)
+ defaultiface=$name
+ defaultclass=$netclass
+ run iptables -t mangle -A out-classify -g mark-to-$netclass
+ ;;
+ *)
+ run iptables -t mangle -A in-$name -s $addr -g mark-from-$netclass
+ run iptables -t mangle -A out-classify -d $addr -g mark-to-$netclass
+ allnets="$allnets $name:$addr"
+ ;;
+ esac
+ done
+}
+
+## defvpn IFACE CLASS NET HOST:ADDR ...
+##
+## Defines a VPN interface. If the interface has the form `ROOT+' (i.e., a
+## netfilter wildcard) then define a separate interface ROOTHOST routing to
+## ADDR; otherwise just write a blanket rule allowing the whole NET. All
+## addresses concerned are put in the named CLASS.
+defvpn () {
+ set -e
+ iface=$1 class=$2 net=$3; shift 3
+ case $iface in
+ *-+)
+ root=${iface%+}
+ for host; do
+ name=${host%:*} addr=${host#*:}
+ defiface $root$name $class:$addr
+ done
+ ;;
+ *)
+ defiface $iface $class:$net
+ ;;
+ esac
+}
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### ICMP filtering for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(50)m4_dnl
+###--------------------------------------------------------------------------
+### ICMP filtering.
+
+clearchain check-icmp
+
+## Ping needs inspecting on a host-by-host basis.
+for type in echo-request echo-reply; do
+ run iptables -A check-icmp -p icmp --icmp-type $type -j RETURN
+done
+
+## Certainly don't allow ping to broadcast addresses.
+run iptables -A check-icmp -g forbidden \
+ -p icmp --icmp-type echo-request \
+ -m addrtype --dst-type BROADCAST
+
+m4_divert(58)m4_dnl
+## Other ICMP is basically benign, we claim.
+run iptables -A check-icmp -j ACCEPT
+
+## Done.
+for i in INPUT FORWARD; do
+ run iptables -A $i -p icmp -j check-icmp
+done
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Local firewall configuration
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### Packet classification.
+
+## Define the available network classes.
+m4_divert(42)m4_dnl
+defnetclass untrusted untrusted trusted
+defnetclass trusted untrusted trusted safe noloop
+defnetclass safe trusted safe noloop
+defnetclass noloop trusted safe
+m4_divert(-1)m4_dnl
+
+###--------------------------------------------------------------------------
+### Network layout.
+
+m4_divert(46)m4_dnl
+## Networks and routing.
+
+defiface $if_trusted \
+ trusted:172.29.199.0/26 \
+ safe:172.29.199.64/27 \
+ untrusted:default
+defiface $if_untrusted \
+ untrusted:172.29.198.0/24
+defvpn $if_vpn safe 172.29.199.128/27 \
+ crybaby:172.29.199.129
+defiface $if_its_mz safe:172.29.199.160/30
+defiface $if_its_pi safe:192.168.0.0/24
+
+m4_divert(60)m4_dnl
+###--------------------------------------------------------------------------
+### Special forwarding exemptions.
+
+## Allow ping from safe/noloop to untrusted networks.
+run iptables -A FORWARD -j ACCEPT \
+ -p icmp --icmp-type echo-request \
+ -m mark --mark $to_untrusted/$MASK_TO
+run iptables -A FORWARD -j ACCEPT \
+ -p icmp --icmp-type echo-reply \
+ -m mark --mark $from_untrusted/$MASK_FROM \
+ -m state --state ESTABLISHED
+
+## Allow SSH from safe/noloop to untrusted networks.
+run iptables -A FORWARD -j ACCEPT \
+ -p tcp --destination-port $port_ssh \
+ -m mark --mark $to_untrusted/$MASK_TO
+run iptables -A FORWARD -j ACCEPT \
+ -p tcp --source-port $port_ssh \
+ -m mark --mark $from_untrusted/$MASK_FROM \
+ -m state --state ESTABLISHED
+
+m4_divert(80)m4_dnl
+###--------------------------------------------------------------------------
+### Locally-bound packet inspection.
+
+clearchain inbound
+
+## Track connections.
+conntrack inbound
+
+## Allow incoming bootp. Bootp won't be forwarded, so this is obviously a
+## local request.
+run iptables -A inbound -j ACCEPT \
+ -s 0.0.0.0 -d 255.255.255.255 \
+ -p udp --source-port $port_bootpc --destination-port $port_bootps
+run iptables -A inbound -j ACCEPT \
+ -s 172.29.198.0/23 \
+ -p udp --source-port $port_bootpc --destination-port $port_bootps
+
+## Allow incoming ping. This is the only ICMP left.
+run iptables -A inbound -j ACCEPT -p icmp
+
+m4_divert(88)m4_dnl
+## Allow unusual things.
+openports inbound
+
+## Inspect inbound packets from untrusted sources.
+run iptables -A inbound -j forbidden
+run iptables -A INPUT -m mark --mark $from_untrusted/$MASK_FROM -g inbound
+
+## Otherwise process as indicated by the mark.
+for i in INPUT FORWARD; do
+ run iptables -A $i -m mark ! --mark 0/$MASK_MASK -j ACCEPT
+done
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### Local configuration makefile.
+
+MAIN_M4_SOURCES += local.m4
+
+HOSTS += metalzone
+HOSTS += vampire
--- /dev/null
+### -*-m4-*-
+###
+### Firewall configuration for metalzone
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### Network interfaces.
+
+m4_divert(44)m4_dnl
+## Interface definitions.
+if_untrusted=eth0
+if_trusted=eth0
+if_vpn=eth0
+if_its_mz=its-mz
+if_its_pi=its-pi
+
+m4_divert(-1)
+###--------------------------------------------------------------------------
+### metalzone-specific rules.
+
+m4_divert(82)m4_dnl
+## Externally visible services.
+allowservices inbound tcp \
+ finger ident \
+ ssh \
+ smtp \
+ gnutella_svc \
+ ftp ftp_data \
+ rsync \
+ http https \
+ git
+allowservices inbound udp \
+ tripe \
+ gnutella_svc
+
+## Provide DNS resolution to local untrusted hosts.
+for p in tcp udp; do
+ run iptables -A inbound -j ACCEPT \
+ -s 172.29.198.0/24 \
+ -p $p --destination-port $port_dns
+done
+
+## Other interesting things.
+dnsresolver inbound
+ntpclient inbound 158.152.1.76 158.152.1.204 194.159.253.2
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Useful numbers for firewall configuration
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(25)m4_dnl
+###--------------------------------------------------------------------------
+### Port numbers.
+
+defport ftp_data 20
+defport ftp 21
+defport ssh 22
+defport smtp 25
+defport dns 53
+defport bootps 67
+defport bootpc 68
+defport finger 79
+defport http 80
+defport ident 113
+defport https 443
+defport syslog 514 # UDP only!
+defport rsync 873
+defport squid 3128
+defport tripe 4070
+defport postgresql 5432
+defport gnutella_svc 6346
+defport git 9418
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Failsafe prologue for firewall scripts
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_divert(10)m4_dnl
+###--------------------------------------------------------------------------
+### Failsafe prologue.
+
+revert () {
+ echo "$1! Retreating to safe version..."
+ if ! "$firewall_failsafe" revert; then
+ echo >&2 "Safe firewall failed. You're screwed. Good luck."
+ exit 1
+ fi
+ echo >&2 "Phew! Fallback to safe version successful."
+ exit 1
+}
+
+finished () {
+ echo "Done."
+ exit 0
+}
+
+exit_after_clearing=:
+export FWCOOKIE=magical
+case "${1-update}" in
+ start | restart | reload | force-reload)
+ echo -n "Starting up firewall... "
+ "$firewall_script" install || revert "Failed"
+ finished
+ ;;
+ stop)
+ echo -n "Shutting down firewall... "
+ exit_after_clearing=finished
+ ;;
+ update)
+ echo -n "Installing new firewall... "
+ "$firewall_script" install || revert "Failed"
+ echo "Done."
+ echo "Can you hear me?"
+ parent=$$
+ (sleep 5; kill $parent; revert "Timeout")&
+ child=$!
+ read answer
+ kill $child
+ case "$answer" in
+ y* | Y*)
+ echo "Cool. We're done here."
+ exit 0
+ ;;
+ esac
+ revert "Bogus"
+ ;;
+ install | revert)
+ ;;
+ *)
+ echo >&2 "Usage: firewall start|stop|reload|restart|force-reload|update|install|revert"
+ exit 1
+ ;;
+esac
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+### -*-m4-*-
+###
+### Firewall configuration for vampire
+###
+### (c) 2008 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### Network interfaces.
+
+m4_divert(44)m4_dnl
+## Interface definitions.
+if_untrusted=eth0.1
+if_trusted=eth0.0
+if_vpn=vpn-+
+if_its_mz=eth0.0
+if_its_pi=eth0.0
+
+m4_divert(-1)
+###--------------------------------------------------------------------------
+### vampire-specific rules.
+
+m4_divert(82)m4_dnl
+## Externally visible services.
+allowservices inbound tcp \
+ finger ident \
+ dns \
+ ssh \
+ smtp \
+ gnutella_svc \
+ ftp ftp_data \
+ rsync \
+ http https \
+ git
+allowservices inbound udp \
+ dns \
+ tripe \
+ gnutella_svc
+
+## Provide DNS resolution to local untrusted hosts.
+for p in tcp udp; do
+ run iptables -A inbound -j ACCEPT \
+ -s 172.29.198.0/24 \
+ -p $p --destination-port $port_dns
+done
+
+## Provide syslog for evolution.
+run iptables -A inbound -j ACCEPT \
+ -s 172.29.198.2 \
+ -p udp --destination-port $port_syslog
+
+## Provide a web cache to local untrusted hosts.
+run iptables -A inbound -j ACCEPT \
+ -s 172.29.198.0/24 \
+ -p tcp --destination-port $port_squid
+
+## Other interesting things.
+dnsresolver inbound
+ntpclient inbound 158.152.1.76 158.152.1.204 194.159.253.2
+
+m4_divert(-1)
+###----- That's all, folks --------------------------------------------------