TARGETS += dummy.sh
dummy.sh: base.m4 prologue.m4 dummy-payload.m4
- $(V_M4) $^ >$@.new && chmod +x $@.new && mv $@.new $@
+ $(V_M4)-DFWHOST=testing $^ >$@.new
+ $(V_AT)chmod +x $@.new && mv $@.new $@
TARGETS += dummy-inst.sh
dummy-inst.sh: dummy.sh
$(V_AT)chmod +x $@.new && mv $@.new $@
###--------------------------------------------------------------------------
+### Other utilities.
+
+## A list of diversions in ascending numerical order.
+CLEANFILES += divs
+divs: $(M4_SOURCES) $(addsuffix .m4,$(HOSTS))
+ $(V_GEN)grep -n m4_divert $^ | \
+ grep -v 'm4_divert(-1)' | \
+ sort -t\( -k2n >$@
+
+###--------------------------------------------------------------------------
### Building.
all: $(TARGETS)
.PHONY: all
%.sh: %.m4 $(M4_SOURCES)
- $(V_M4)base.m4 $*.m4 $(MAIN_M4_SOURCES) >$@.new
+ $(V_M4)-DFWHOST=$* base.m4 $*.m4 $(MAIN_M4_SOURCES) >$@.new
$(V_AT)chmod +x $@.new && mv $@.new $@
-clean:; rm -f $(TARGETS) *.new
+clean:; rm -f $(TARGETS) *.new $(CLEANFILES)
.PHONY: clean
###--------------------------------------------------------------------------
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### artist-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
## Externally visible services.
allowservices inbound tcp \
ssh \
### Overall structure.
###
### 0 File header: shebang, do-not-edit warning. [base]
-### 5 Configuration. [config]
+### 4 Configuration. [config]
+### 6 Local settings. [local]
### 10 Prologue: command-line parsing and failsafe. [prologue]
### 20 Function definitions. [functions]
-### 25 Port numbers etc. [numbers]
+### 24 Port numbers etc. [numbers]
+### 26 Networks, hosts and interfaces. [local]
### 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]
### 38 Utility chains. [functions]
### 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]
+### 50 Packet filter. [bookends]
+### 60 ICMP filtering. [icmp]
+### 62 Local configuration. [local]
+### 68 Finally accept ICMP, hook onto INPUT and FORWARD. [icmp]
+### 80 Local configuration. [local]
+### 84 Locally bound packet inspection. [local]
+### 86 Per-host configuration. [HOST]
+### 88 Final filtering. [local]
### 90 Finishing touches. [bookends]
### 94 Set final policies. [bookends]
### 99 File footer: do-not-edit warning. [base]
m4_divert(0)m4_dnl
#! /bin/sh
+<:###:> Firewall script for FWHOST
+###
+### *** GENERATED FILE: DO NOT EDIT ***
+
### BEGIN INIT INFO
# Provides: firewall
# Required-Start: mountkernfs
# Default-Stop: 0 6
# Description: Provides customized packet filter rules.
### END INIT INFO
-### *** GENERATED FILE: DO NOT EDIT ***
set -e
PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
+fwhost=FWHOST
m4_divert(99)m4_dnl
### *** GENERATED FILE: DO NOT EDIT ***
## Set forwarding options. Apparently setting ip_forward clobbers other
## settings, so put this first.
+case $host_type_<::>FWHOST in
+ router) forward=1 ;;
+ *) forward=0 ;;
+esac
setopt ip_forward $forward
setdevopt forwarding $forward
fi
fi
-## Turn on the reverse-path filter, and log weird things.
-setdevopt rp_filter $rp_filter
-setdevopt log_martians $log_martians
+## Turn off the reverse-path filter. It's basically useless: the filter does
+## nothing at all for single-homed hosts; and multi-homed hosts tend to have
+## routing aysmmetries if there's any kind of cycle.
+setdevopt rp_filter 0
+setdevopt log_martians 0
## Turn off things which can mess with our routing decisions.
setdevopt accept_source_route 0
errorchain interesting ACCEPT
## Not an error, just log interesting packets.
-m4_divert(36)m4_dnl
+m4_divert(50)m4_dnl
###--------------------------------------------------------------------------
### Standard filtering.
-d ::1
## We shouldn't be asked to forward things with link-local addresses.
-run iptables -A FORWARD -g bad-source-address \
- -s 169.254.0.0/16
-run iptables -A FORWARD -g bad-destination-address \
- -d 169.254.0.0/16
-run ip6tables -A FORWARD -g bad-source-address \
- -s fe80::/10
-run ip6tables -A FORWARD -g bad-destination-address \
- -d fe80::/10
+case $forward in
+ 1)
+ run iptables -A FORWARD -g bad-source-address \
+ -s 169.254.0.0/16
+ run iptables -A FORWARD -g bad-destination-address \
+ -d 169.254.0.0/16
+ run ip6tables -A FORWARD -g bad-source-address \
+ -s fe80::/10
+ run ip6tables -A FORWARD -g bad-destination-address \
+ -d fe80::/10
+ ;;
+esac
## Also, don't forward link-local broadcast or multicast.
-run iptables -A FORWARD -g bad-destination-address \
- -d 255.255.255.255
-run iptables -A FORWARD -g bad-destination-address \
- -m addrtype --dst-type BROADCAST
-run iptables -A FORWARD -g bad-destination-address \
- -d 224.0.0.0/24
-for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
- run ip6tables -A FORWARD -g bad-destination-address \
- -d fe${x}2::/16
-done
+case $forward in
+ 1)
+ run iptables -A FORWARD -g bad-destination-address \
+ -d 255.255.255.255
+ run iptables -A FORWARD -g bad-destination-address \
+ -m addrtype --dst-type BROADCAST
+ run iptables -A FORWARD -g bad-destination-address \
+ -d 224.0.0.0/24
+ for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+ run ip6tables -A FORWARD -g bad-destination-address \
+ -d fe${x}2::/16
+ done
+ ;;
+esac
## Add a hook for fail2ban.
clearchain fail2ban
done
done
+## Dump the resulting configuration.
+if [ "$FW_DEBUG" ]; then
+ for ip in ip ip6; do
+ for table in mangle filter; do
+ echo "----- $ip $table -----"
+ echo
+ ${ip}tables -t $table -nvL
+ echo
+ done
+ done
+fi
+
m4_divert(-1)
###----- That's all, folks --------------------------------------------------
done
m4_divert(46)m4_dnl
-## Mark addresses reachable on non-default interfaces as not reachable on the
-## default interface.
-trace "nets = $allnets $allnets6"
+## Build the input classification chains. There's one chain `in-IFACE' for
+## each local interface. This chain does a further dispatch on the source
+## address to the appropriate `mark-from-CLASS' chain for the source network
+## class.
+seen=:
+for iface in $host_ifaces_<::>FWHOST; do
+ ifname=${iface%=*}
+ case $seen in *:$ifname:*) continue ;; esac
+ seen=$seen$ifname:
+ clearchain mangle:in-$ifname
+ run ip46tables -t mangle -A in-classify -i $ifname -g in-$ifname
+done
+
+## Now populate the `in-IFACE' and `out-classify' chains. We iterate over
+## the available networks and add addresses to the appropriate chains. Also,
+## build up a map of which interfaces receive from which address ranged so
+## that we can finish the chains off properly later. This contains entries
+## of the form IFACE=:ADDR:ADDR:...:
+ifnets=""
for net in $allnets; do
- defaultp=nil
- for iface in $defaultifaces; do
- case $net in $iface:*) defaultp=t ;; esac
+
+ ## Determine the addresses and class for this network, and populate the
+ ## `out-classify' chains.
+ eval addr=\$net_inet_$net addr6=\$net_inet6_$net class=\$net_class_$net
+ case $class in virtual) continue ;; esac
+ trace "$net : $class"
+ for a in $addr; do
+ run iptables -t mangle -A out-classify -g mark-to-$class -d $a
done
- case $defaultp in
- nil)
- for iface in $defaultifaces; do
- run iptables -t mangle -A in-$iface \
- -s ${net#*:} -g bad-source-address
- done
- ;;
- esac
-done
-for net in $allnets6; do
- defaultp=nil
- for iface in $defaultifaces; do
- case $net in $iface:*) defaultp=t ;; esac
+ for a in $addr6; do
+ run ip6tables -t mangle -A out-classify -g mark-to-$class -d $a
done
- case $defaultp in
- nil)
- for iface in $defaultifaces; do
- run ip6tables -t mangle -A in-$iface \
- -s ${net#*:} -g bad-source-address
+
+ ## Now work through the interfaces.
+ for iface in $(net_interfaces FWHOST $net); do
+ nets=""
+ case $iface in
+
+ -)
+ ## A special `no interface' marker: we should not receive packets
+ ## from this network at all.
+ continue
+ ;;
+
+ *-+)
+ ## A special marker indicating a collection of point-to-point
+ ## interfaces. We should match an address to a particular interface.
+ ## Later, we'll cap this chain off by rejecting all other traffic.
+ eval hosts=\$net_hosts_$net
+ for host in $hosts; do
+ eval ha=\$host_inet_$host ha6=\$host_inet6_$host
+ trace "$host : $class -> $iface"
+ for a in $ha; do
+ run iptables -t mangle -A in-$iface \
+ -i ${iface%+}$host -s $a -g mark-from-$class
+ nets=$nets$a:
+ done
+ for a in $ha6; do
+ run ip6tables -t mangle -A in-$iface \
+ -i ${iface%+}$host -s $a -g mark-from-$class
+ nets=$nets$a:
+ done
+ done
+ ;;
+
+ *)
+ ## A normal interface. Classify incoming traffic according to the
+ ## source address.
+ trace "$net : $class -> $iface"
+ for a in $addr; do
+ run iptables -t mangle -A in-$iface -g mark-from-$class -s $a
+ nets=$nets$a:
+ done
+ for a in $addr6; do
+ run ip6tables -t mangle -A in-$iface -g mark-from-$class -s $a
+ nets=$nets$a:
+ done
+ case $net in default) nets=${nets}default: ;; esac
+ ;;
+ esac
+
+ ## Record that this interface receives traffic from this network.
+ unset nifnets
+ foundp=nil
+ for ifnet in $ifnets; do
+ case $ifnet in
+ $iface=*:$net:*) addword nifnets $ifnet; foundp=t ;;
+ $iface=*) addword nifnets $ifnet$nets; foundp=t ;;
+ *) addword nifnets $ifnet ;;
+ esac
+ done
+ case $foundp in nil) addword nifnets $iface=:$nets ;; esac
+ ifnets=$nifnets
+
+ done
+done
+
+## Wrap up all of the `in-IFACE' chains. A chain which matches the `default'
+## net should have unmatched but known networks blocked off, and then chain
+## onto `in-default'. Other chains should just chain onto
+## `bad-source-address'.
+trace "ifnets = $ifnets"
+for ifnet in $ifnets; do
+ iface=${ifnet%%=*} nets=${ifnet#*=}
+ case $nets in
+ *:default:*)
+ for n in $allnets; do
+ eval addr=\$net_inet_$n addr6=\$net_inet6_$n
+ for a in $addr; do
+ case $nets in *:$a:*) continue ;; esac
+ nets=$nets$a
+ run iptables -t mangle -A in-$iface -s $a -g bad-source-address
+ done
+ for a in $addr6; do
+ case $nets in *:$a:*) continue ;; esac
+ nets=$nets$a
+ run ip6tables -t mangle -A in-$iface -s $a -g bad-source-address
+ done
done
+ run ip46tables -t mangle -A in-$iface -g in-default
+ ;;
+ *)
+ run ip46tables -t mangle -A in-$iface -g bad-source-address
;;
esac
done
do
run ip6tables -t mangle -A in-default -s $addr -g bad-source-address
done
+run ip46tables -t mangle -A in-default -g mark-from-$net_class_default
m4_divert(92)m4_dnl
## Put the final default decision on the in-default chain, and attach the
## classification chains to the PREROUTING hook.
for iface in $defaultifaces; do
- run ip46tables -t mangle -A in-$iface -g mark-from-$defaultclass
+ run ip46tables -t mangle -A in-$iface -g in-default
done
-run ip46tables -t mangle -A out-classify -g mark-to-$defaultclass
+run ip46tables -t mangle -A out-classify -g mark-to-$net_class_default
run ip46tables -t mangle -A PREROUTING -j in-classify
run ip46tables -t mangle -A PREROUTING -j out-classify
### 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
+m4_divert(4)m4_dnl
###--------------------------------------------------------------------------
### Configuration.
## Which chains to preserve.
defconf(preserve_chains, )
-## Whether to permit forwarding.
-defconf(forward, 1)
-
-## Whether to turn on the reverse-path filter.
-defconf(rp_filter, 1)
-
-## Whether to turn on logging of martian packets.
-defconf(log_martians, 1)
-
m4_divert(-1)
###----- That's all, folks --------------------------------------------------
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_untrusted=eth0
-if_dmz=$if_untrusted
-if_safe=$if_dmz
-if_trusted=$if_dmz
-if_vpn=$if_dmz
-if_iodine=$if_dmz
-if_its_mz=$if_dmz
-if_its_pi=$if_dmz
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### fender-specific rules.
m4_divert(82)m4_dnl
eval proto_$name=$number
}
+## addword VAR WORD
+##
+## Adds WORD to the value of the shell variable VAR, if it's not there
+## already. Words are separated by a single space; no leading or trailing
+## spaces are introduced.
+addword () {
+ var=$1 word=$2
+ eval val=\$$var
+ case " $val " in
+ *" $word "*) ;;
+ *) eval "$var=\${$var:+\$val }\$word" ;;
+ esac
+}
+
m4_divert(38)m4_dnl
###--------------------------------------------------------------------------
### Utility chains (used by function definitions).
-m4_divert(22)m4_dnl
+m4_divert(20)m4_dnl
###--------------------------------------------------------------------------
### Basic chain constructions.
run ip46tables -t $table -A $chain -j DROP
}
-m4_divert(24)m4_dnl
+m4_divert(20)m4_dnl
###--------------------------------------------------------------------------
### Basic option setting.
done
}
-m4_divert(26)m4_dnl
+m4_divert(20)m4_dnl
###--------------------------------------------------------------------------
### Packet filter construction.
-m frag --fragfirst
run ip6tables -A accept-non-init-frag -j ACCEPT
-m4_divert(26)m4_dnl
+m4_divert(20)m4_dnl
## allowservices CHAIN PROTO SERVICE ...
##
## Add rules to allow the SERVICES on the CHAIN.
run ip46tables -A $chain -p udp -g interesting --destination-port $1:$2
}
-m4_divert(28)m4_dnl
+m4_divert(20)m4_dnl
###--------------------------------------------------------------------------
### Packet classification.
+###
+### See `classify.m4' for an explanation of how the firewall machinery for
+### packet classification works.
+###
+### A list of all network names is kept in `allnets'. For each network NET,
+### shell variables are defined describing their properties.
+###
+### net_class_NET The class of the network, as defined by
+### `defnetclass'.
+### net_inet_NET List of IPv4 address ranges in the network.
+### net_inet6_NET List of IPv6 address ranges in the network.
+### net_fwd_NET List of other networks that this one forwards to.
+### net_hosts_NET List of hosts known to be in the network.
+### host_inet_HOST IPv4 address of the named HOST.
+### host_inet6_HOST IPv6 address of the named HOST.
+###
+### Similarly, a list of hosts is kept in `allhosts', and for each host HOST,
+### a shell variables are defined:
+###
+### host_ifaces_HOST List of interfaces for this host and the networks
+### they attach to, in the form IFACE=NET.
## defbitfield NAME WIDTH
##
## Pass 1. Establish the from_NAME and to_NAME constants, and the
## netclass's mask bit.
+ trace "netclass $name = $netclassindex"
eval from_$name=$(( $netclassindex << $BIT_FROM ))
eval to_$name=$(( $netclassindex << $BIT_TO ))
eval _mask_$name=$(( 1 << ($netclassindex + $BIT_MASK) ))
netclassindex=$(( $netclassindex + 1 ))
}
-## defiface NAME[,NAME,...] NETCLASS:NETWORK/MASK...
-##
-## Declares network interfaces with the given NAMEs and associates with them
-## 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=:
-defaultifaces=""
-allnets= allnets6=
-defiface () {
- set -e
- names=$1; shift
- seen=:
- for name in $(echo $names | sed 'y/,/ /'); do
- case $seen in *:"$name":*) continue ;; esac
- seen=$seen$name:
- case $ifaces in
- *:"$name":*) ;;
- *)
- clearchain mangle:in-$name
- run ip46tables -t mangle -A in-classify -i $name -g in-$name
- ;;
+## defnet NET CLASS
+##
+## Define a network. Follow by calls to `addr', `forwards', etc. to define
+## properties of the network. Networks are processed in order, so if their
+## addresses overlap then the more specific addresses should be defined
+## earlier.
+defnet () {
+ net=$1 class=$2
+ addword allnets $net
+ eval net_class_$1=\$class
+}
+
+## addr ADDRESS/LEN ...
+##
+## Define addresses for the network being defined. ADDRESSes are in
+## colon-separated IPv6 or dotted-quad IPv4 form.
+addr () {
+ for i in "$@"; do
+ case "$i" in
+ *:*) addword net_inet6_$net $i ;;
+ *) addword net_inet_$net $i ;;
esac
- ifaces=$ifaces$name:
- for item; do
- netclass=${item%:*} addr=${item#*:}
- case $addr in
- default)
- case "$defaultifaces,$defaultclass" in
- ,* | *,$netclass)
- defaultifaces="$defaultifaces $name"
- defaultclass=$netclass
- ;;
- *)
- echo >&2 "$0: inconsistent default netclasses"
- exit 1
- ;;
- esac
- ;;
- *:*)
- run ip6tables -t mangle -A in-$name -g mark-from-$netclass \
- -s $addr
- run ip6tables -t mangle -A out-classify -g mark-to-$netclass \
- -d $addr
- allnets6="$allnets6 $name:$addr"
- ;;
- *)
- run iptables -t mangle -A in-$name -g mark-from-$netclass \
- -s $addr
- run iptables -t mangle -A out-classify -g mark-to-$netclass \
- -d $addr
- allnets="$allnets $name:$addr"
- ;;
- esac
- done
done
}
-## defvpn IFACE CLASS NET HOST:ADDR ...
+## forwards NET ...
##
-## 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
- ;;
+## Declare that packets from this network are forwarded to the other NETs.
+forwards () {
+ eval "net_fwd_$net=\"$*\""
+}
+
+## noxit NET ...
+##
+## Declare that packets from this network must not be forwarded to the other
+## NETs.
+noxit () {
+ eval "net_noxit_$net=\"$*\""
+}
+
+## host HOST ADDR ...
+##
+## Define the address of an individual host on the current network. The
+## ADDRs may be full IPv4 or IPv6 addresses, or offsets from the containing
+## network address, which is a simple number for IPv4, or a suffix beginning
+## with `::' for IPv6. If an IPv6 base address is provided for the network
+## but not for the host then the host's IPv4 address is used as a suffix.
+host () {
+ name=$1; shift
+
+ ## Work out which addresses we've actually been given.
+ unset a6
+ for i in "$@"; do
+ case "$i" in ::*) a6=$i ;; *) a=$i ;; esac
+ done
+ case "${a+t}" in
+ t) ;;
+ *) echo >&2 "$0: no address for $name"; exit 1 ;;
esac
+ case "${a6+t}" in t) ;; *) a6=::$a ;; esac
+
+ ## Work out the IPv4 address.
+ eval nn=\$net_inet_$net
+ for n in $nn; do
+ addr=${n%/*}
+ base=${addr%.*}
+ offset=${addr##*.}
+ case $a in *.*) aa=$a ;; *) aa=$base.$(( $offset + $a )) ;; esac
+ eval host_inet_$name=$aa
+ done
+
+ ## Work out the IPv6 address.
+ eval nn=\$net_inet6_$net
+ for n in $nn; do
+ addr=${n%/*}
+ base=${addr%::*}
+ case $a in ::*) aa=$addr$a ;; *) aa=$a ;; esac
+ eval host_inet6_$name=$aa
+ done
+
+ ## Remember the host in the list.
+ addword net_hosts_$net $name
+}
+
+## defhost NAME
+##
+## Define a new host. Follow by calls to `iface' to define the host's
+## interfaces.
+defhost () {
+ host=$1
+ addword allhosts $host
+ eval host_type_$host=endsys
+}
+
+## router
+##
+## Declare the host to be a router, so it should forward packets and so on.
+router () {
+ eval host_type_$host=router
+}
+
+## iface IFACE NET ...
+##
+## Define a host's interfaces. Specifically, declares that the host has an
+## interface IFACE attached to the listed NETs.
+iface () {
+ name=$1; shift
+ for net in "$@"; do
+ addword host_ifaces_$host $name=$net
+ done
+}
+
+## net_interfaces HOST NET
+##
+## Determine the interfaces on which packets may plausibly arrive from the
+## named NET. Returns `-' if no such interface exists.
+##
+## This algorithm is not very clever. It's just about barely good enough to
+## deduce transitivity through a simple routed network; with complicated
+## networks, it will undoubtedly give wrong answers. Check the results
+## carefully, and, if necessary, list the connectivity explicitly; use the
+## special interface `-' for networks you know shouldn't send packets to a
+## host.
+net_interfaces () {
+ host=$1 startnet=$2
+
+ ## Determine the locally attached networks.
+ targets=:
+ eval ii=\$host_ifaces_$host
+ for i in $ii; do targets=$targets$i:; done
+
+ ## Determine the transitivity.
+ seen=:
+ nets=$startnet
+ while :; do
+
+ ## First pass. Determine whether any of the networks we're considering
+ ## are in the target set. If they are, then return the corresponding
+ ## interfaces.
+ found=""
+ for net in $nets; do
+ tg=$targets
+ while :; do
+ any=nil
+ case $tg in
+ *"=$net:"*)
+ n=${tg%=$net:*}; tg=${n%:*}:; n=${n##*:}
+ addword found $n
+ any=t
+ ;;
+ esac
+ case $any in nil) break ;; esac
+ done
+ done
+ case "$found" in ?*) echo $found; return ;; esac
+
+ ## No joy. Determine the set of networks which (a) these ones can
+ ## forward to, and (b) that we've not considered already. These are the
+ ## nets we'll consider next time around.
+ nextnets=""
+ any=nil
+ for net in $nets; do
+ eval fwd=\$net_fwd_$net
+ for n in $fwd; do
+ case $seen in *":$n:"*) continue ;; esac
+ seen=$seen$n:
+ eval noxit=\$net_noxit_$n
+ case " $noxit " in *" $startnet "*) continue ;; esac
+ case " $nextnets " in
+ *" $n "*) ;;
+ *) addword nextnets $n; any=t ;;
+ esac
+ done
+ done
+
+ ## If we've run out of networks then there's no reachability. Return a
+ ## failure.
+ case $any in nil) echo -; return ;; esac
+ nets=$nextnets
+ done
}
m4_divert(-1)
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_trusted=eth0
-if_dmz=$if_trusted
-if_safe=$if_dmz
-if_untrusted=$if_dmz
-if_vpn=$if_dmz
-if_iodine=$if_dmz
-if_its_mz=$if_dmz
-if_its_pi=$if_dmz
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### gibson-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
## Externally visible services.
allowservices inbound tcp \
ssh \
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=br-dmz
-if_trusted=br-unsafe
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### ibanez-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
## Externally visible services.
allowservices inbound tcp \
ssh \
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### jem-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
## Set up the SAUCE sinbin. Unfortunately, ipset is a bit brittle. This
## isn't a completely critical part of the firewall security, so don't make
## this fail the entire script.
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
+### Local configuration.
+
+m4_divert(6)m4_dnl
+## Default NTP servers.
+defconf(ntp_servers,
+ "158.152.1.76 158.152.1.204 194.159.253.2 195.173.57.232")
+
+m4_divert(-1)
+###--------------------------------------------------------------------------
### Packet classification.
## Define the available network classes.
defnetclass trusted untrusted trusted safe noloop
defnetclass safe trusted safe noloop
defnetclass noloop trusted safe
-m4_divert(-1)m4_dnl
+m4_divert(-1)
+m4_divert(26)m4_dnl
###--------------------------------------------------------------------------
### Network layout.
-m4_divert(46)m4_dnl
-## Networks and routing.
-
-defiface $if_dmz \
- trusted:62.49.204.144/28 \
- trusted:172.29.199.0/25 \
- untrusted:default
-defiface $if_trusted \
- trusted:172.29.199.0/25 \
- untrusted:default
-defiface $if_safe safe:172.29.199.192/26
-defiface $if_untrusted \
- untrusted:172.29.198.0/25
-defvpn $if_vpn safe 172.29.199.128/27 \
- crybaby:172.29.199.129 \
- terror:172.29.199.130
-defiface $if_iodine untrusted:172.29.198.128/28
-defiface $if_its_mz safe:172.29.199.160/30
-defiface $if_its_pi safe:192.168.0.0/24
+## House networks.
+defnet dmz trusted
+ addr 62.49.204.144/28
+ forwards unsafe untrusted
+defnet unsafe trusted
+ addr 172.29.199.0/25
+ forwards househub
+defnet safe safe
+ addr 172.29.199.192/28
+ forwards househub
+defnet untrusted untrusted
+ addr 172.29.198.0/25
+ forwards househub
+defnet vpn safe
+ addr 172.29.199.128/27
+ forwards househub
+ host crybaby 1
+ host terror 2
+defnet iodine untrusted
+ addr 172.29.198.128/28
-## Default NTP servers.
-ntp_servers="158.152.1.76 158.152.1.204 194.159.253.2 195.173.57.232"
+defnet househub virtual
+ forwards housebdry dmz unsafe safe untrusted
+defnet housebdry virtual
+ forwards househub hub
+ noxit dmz
+
+## House hosts.
+defhost radius
+ router
+ iface eth0 dmz
+ iface eth1 unsafe
+ iface eth2 safe
+ iface eth3 untrusted
+defhost roadstar
+ iface eth0 dmz
+ iface eth1 unsafe
+defhost jem
+ iface eth0 dmz
+ iface eth1 unsafe
+defhost artist
+ iface eth0 dmz
+ iface eth1 unsafe
+defhost vampire
+ router
+ iface eth0.0 dmz
+ iface eth0.1 unsafe
+ iface eth0.3 untrusted
+ iface dns0 dns
+ iface vpn-+ vpn
+ iface vpn-precision colobdry vpn
+defhost ibanez
+ iface br-dmz dmz
+ iface br-unsafe unsafe
+
+defhost gibson
+ iface eth0 unsafe
+
+## Colocated networks.
+defnet jump trusted
+ addr 212.13.198.64/28
+ forwards colohub
+defnet colo trusted
+ addr 172.29.199.176/28
+ forwards colohub
+defnet colohub virtual
+ forwards colobdry jump colo
+defnet colobdry virtual
+ forwards colohub hub
+ noxit jump
-m4_divert(60)m4_dnl
+## Colocated hosts.
+defhost fender
+ iface br-jump jump
+ iface br-colo colo
+defhost precision
+ router
+ iface eth0 jump
+ iface eth1 colo
+ iface vpn-+ vpn
+ iface vpn-vampire housebdry vpn
+defhost telecaster
+ iface eth0 jump
+ iface eth1 colo
+defhost stratocaster
+ iface eth0 jump
+ iface eth1 colo
+defhost jazz
+ iface eth0 jump
+ iface eth1 colo
+
+## Other networks.
+defnet hub virtual
+ forwards housebdry colobdry
+defnet default untrusted
+ addr 62.49.204.144/28
+ addr 212.13.198.64/28
+ forwards dmz untrusted unsafe jump colo
+
+m4_divert(80)m4_dnl
###--------------------------------------------------------------------------
### Special forwarding exemptions.
-## Only allow these packets if they're not fragmented. (Don't trust safe
-## hosts's fragment reassembly to be robust against malicious fragments.)
-## There's a hideous bug in iptables 1.4.11.1 which botches the meaning of
-## `! -f', so we do the negation using early return from a subchain.
-clearchain fwd-spec-nofrag
-run iptables -A fwd-spec-nofrag -j RETURN --fragment
-run ip6tables -A fwd-spec-nofrag -j RETURN \
- -m ipv6header --soft --header frag
-run iptables -A FORWARD -j fwd-spec-nofrag
-
-## Allow ping from safe/noloop to untrusted networks.
-run iptables -A fwd-spec-nofrag -j ACCEPT \
- -p icmp --icmp-type echo-request \
- -m mark --mark $to_untrusted/$MASK_TO
-run iptables -A fwd-spec-nofrag -j ACCEPT \
- -p icmp --icmp-type echo-reply \
- -m mark --mark $from_untrusted/$MASK_FROM \
- -m state --state ESTABLISHED
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
- -p ipv6-icmp --icmpv6-type echo-request \
- -m mark --mark $to_untrusted/$MASK_TO
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
- -p ipv6-icmp --icmpv6-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 fwd-spec-nofrag -j ACCEPT \
- -p tcp --destination-port $port_ssh \
- -m mark --mark $to_untrusted/$MASK_TO
-run iptables -A fwd-spec-nofrag -j ACCEPT \
- -p tcp --source-port $port_ssh \
- -m mark --mark $from_untrusted/$MASK_FROM \
- -m state --state ESTABLISHED
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
- -p tcp --destination-port $port_ssh \
- -m mark --mark $to_untrusted/$MASK_TO
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
- -p tcp --source-port $port_ssh \
- -m mark --mark $from_untrusted/$MASK_FROM \
- -m state --state ESTABLISHED
-
-m4_divert(60)m4_dnl
+case $forward in
+ 1)
+
+ ## Only allow these packets if they're not fragmented. (Don't trust safe
+ ## hosts's fragment reassembly to be robust against malicious fragments.)
+ ## There's a hideous bug in iptables 1.4.11.1 which botches the meaning
+ ## of `! -f', so we do the negation using early return from a subchain.
+ clearchain fwd-spec-nofrag
+ run iptables -A fwd-spec-nofrag -j RETURN --fragment
+ run ip6tables -A fwd-spec-nofrag -j RETURN \
+ -m ipv6header --soft --header frag
+ run iptables -A FORWARD -j fwd-spec-nofrag
+
+ ## Allow ping from safe/noloop to untrusted networks.
+ run iptables -A fwd-spec-nofrag -j ACCEPT \
+ -p icmp --icmp-type echo-request \
+ -m mark --mark $to_untrusted/$MASK_TO
+ run iptables -A fwd-spec-nofrag -j ACCEPT \
+ -p icmp --icmp-type echo-reply \
+ -m mark --mark $from_untrusted/$MASK_FROM \
+ -m state --state ESTABLISHED
+ run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+ -p ipv6-icmp --icmpv6-type echo-request \
+ -m mark --mark $to_untrusted/$MASK_TO
+ run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+ -p ipv6-icmp --icmpv6-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 fwd-spec-nofrag -j ACCEPT \
+ -p tcp --destination-port $port_ssh \
+ -m mark --mark $to_untrusted/$MASK_TO
+ run iptables -A fwd-spec-nofrag -j ACCEPT \
+ -p tcp --source-port $port_ssh \
+ -m mark --mark $from_untrusted/$MASK_FROM \
+ -m state --state ESTABLISHED
+ run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+ -p tcp --destination-port $port_ssh \
+ -m mark --mark $to_untrusted/$MASK_TO
+ run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+ -p tcp --source-port $port_ssh \
+ -m mark --mark $from_untrusted/$MASK_FROM \
+ -m state --state ESTABLISHED
+
+ ;;
+esac
+
+m4_divert(80)m4_dnl
###--------------------------------------------------------------------------
### Kill things we don't understand properly.
###
errorchain poorly-understood REJECT
## Ban multicast destination addresses in forwarding.
-run iptables -A FORWARD -g poorly-understood \
- -d 224.0.0.0/4
-run ip6tables -A FORWARD -g poorly-understood \
- -d ff::/8
+case $forward in
+ 1)
+ run iptables -A FORWARD -g poorly-understood \
+ -d 224.0.0.0/4
+ run ip6tables -A FORWARD -g poorly-understood \
+ -d ff::/8
+ ;;
+esac
-m4_divert(80)m4_dnl
+m4_divert(84)m4_dnl
###--------------------------------------------------------------------------
### Locally-bound packet inspection.
run ip46tables -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 ip46tables -A $i -m mark ! --mark 0/$MASK_MASK -j ACCEPT
-done
+run ip46tables -A INPUT -m mark ! --mark 0/$MASK_MASK -j ACCEPT
+case $forward in
+ 1)
+ run ip46tables -A FORWARD -m mark ! --mark 0/$MASK_MASK -j ACCEPT
+ ;;
+esac
m4_divert(-1)
###----- That's all, folks --------------------------------------------------
### 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
+m4_divert(24)m4_dnl
###--------------------------------------------------------------------------
### Magic numbers.
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This router is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=eth2
-if_untrusted=eth3
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### radius-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
## Externally visible services.
allowservices inbound tcp \
ident \
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### roadstar-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
## Externally visible services.
allowservices inbound tcp \
ssh \
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###--------------------------------------------------------------------------
-### Config settings.
-
-## This router is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0.0
-if_trusted=eth0.1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=eth0.3
-if_vpn=vpn-+
-if_iodine=dns+
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
### vampire-specific rules.
-m4_divert(82)m4_dnl
+m4_divert(86)m4_dnl
## Externally visible services.
allowservices inbound tcp \
finger ident \
run iptables -t nat -X
run iptables -t nat -N outbound
-run iptables -t nat -A outbound -j RETURN ! -o $if_dmz
+run iptables -t nat -A outbound -j RETURN ! -o eth0.0
run iptables -t nat -A outbound -j RETURN ! -s 172.29.198.0/23
run iptables -t nat -A outbound -j RETURN -d 62.49.204.144/28
run iptables -t nat -A outbound -j RETURN -d 172.29.198.0/23